本笔记摘抄自:https://www.cnblogs.com/zhili/archive/2012/07/23/Mutex_And_Semaphore.html,记录一下学习过程以备后续查用。

    一、信号量(Semaphore)

信号量(Semaphore)是由内核对象维护的int变量。当信号量为0时,在信号量上等待的线程会堵塞;信号量大于0时,就解除堵塞。当在一个信号量上等待

的线程解除堵塞时,内核自动会将信号量的计数减1。在.NET下通过Semaphore类来实现信号量同步。

Semaphore类限制可同时访问某一资源或资源池的线程数。线程通过调用 WaitOne方法将信号量减1,并通过调用Release方法把信号量加1。

先说下构造函数:

public Semaphore(int initialCount,int maximumCount);通过两个参数来设置信号的初始计数和最大计数。

下面代码演示信号量同步的使用:

    class Program
{
//共享资源
public static int number = ;
//初始信号量计数为0,最大计数为10。
public static Semaphore semaphore = new Semaphore(, );
static void Main(string[] args)
{
#region 线程同步:使用信号量实现同步
for (int i = ; i < ; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(SemaphoreMethod));
thread.Start(i);
} //每次增加2个信号量,即每次释放2个线程。
for (int j = ; j < ; j++)
{
Console.WriteLine("红灯转绿灯……");
semaphore.Release();
Thread.Sleep();
}
Console.Read();
#endregion
} /// <summary>
/// Semaphore方法
/// </summary>
public static void SemaphoreMethod(object parameter)
{
while ((int)parameter != number)
{
Thread.Sleep();
}
//信号量计数减1
semaphore.WaitOne();
Console.WriteLine("The current value of number is:{0}", ++number);
}
}

运行结果如下:

与上一篇AutoResetEvent类似,信号量也可以实现跨进程间的线程同步。通过调用public Semaphore(int initialCount,int maximumCount,string name);

构造函数,传入一个信号量名来实现此功能。

下面代码演示跨进程间的线程同步:

第一个进程代码:

    class Program
{
//共享资源
public static int number = ; //初始信号量计数为0,最大计数为10。
public static Semaphore semaphore1 = new Semaphore(, , "Semaphore1");
public static Semaphore semaphore2 = new Semaphore(, , "Semaphore2"); static void Main(string[] args)
{
#region 线程同步:使用信号量实现跨进程之间的线程同步
for (int i = ; i < ; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(Semaphore1Method));
thread.Start(i);
} //为了有时间去启动另外一个进程
Thread.Sleep(); //每次增加2个信号量,即每次释放2个线程。
for (int j = ; j < ; j++)
{
Console.WriteLine("信号灯1红灯转绿灯……");
semaphore1.Release();
Console.WriteLine("信号灯2红灯转绿灯……");
semaphore2.Release();
Thread.Sleep();
}
Console.Read();
#endregion
} /// <summary>
/// Semaphore1方法
/// </summary>
public static void Semaphore1Method(object parameter)
{
while ((int)parameter != number)
{
Thread.Sleep();
}
//信号量计数减1
semaphore1.WaitOne();
Console.WriteLine("Semaphore1:The current value of number is:{0}", ++number);
}
}

第二个进程代码:

    class Program
{
//共享资源
public static int number = ;
//创建对象
public static Semaphore semaphore2 = new Semaphore(, , "Semaphore2"); static void Main(string[] args)
{
#region 通过信号量实现跨进程间的线程同步
for (int i = ; i < ; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(Semaphore2Method));
thread.Start(i);
}
Console.Read();
#endregion
} /// <summary>
/// Semaphore2方法
/// </summary>
public static void Semaphore2Method(object parameter)
{
while ((int)parameter != number)
{
Thread.Sleep();
}
//信号量计数减1
semaphore2.WaitOne();
Console.WriteLine("Semaphore2:The current value of number is:{0}", ++number);
}
}

运行结果如下:

从结果可以看出,第一个进程的semaphore2.Release(2);信号发出后,第二个进程可以收到并释放线程。

二、互斥体(Mutex)

Mutex对象是一个同步基元,当某一个线程占用Mutex对象时,其他也需要占用Mutex的线程将处于挂起状态。

下面代码演示互斥体同步的使用:

    class Program
{
//共享资源
public static int number = ;
//互斥体
public static Mutex mutex = new Mutex(); static void Main(string[] args)
{
#region 线程同步:使用互斥体实现同步
for (int i = ; i < ; i++)
{
Thread thread = new Thread(MutexMethod);
thread.Start();
} Console.Read();
#endregion
} /// <summary>
/// Mutex方法
/// </summary>
public static void MutexMethod(object parameter)
{
mutex.WaitOne();
Thread.Sleep();
Console.WriteLine("The current value of number is:{0}", ++number);
mutex.ReleaseMutex();
}
}

运行结果如下:

下面代码演示跨进程间的线程同步:

第一个进程代码:

    class Program
{
//共享资源
public static int number = ; //互斥体
public static Mutex mutex1 = new Mutex(false, "Mutex1");
public static Mutex mutex2 = new Mutex(false, "Mutex2"); static void Main(string[] args)
{
#region 线程同步:使用互斥体实现跨进程之间的线程同步
mutex1.WaitOne();
mutex2.WaitOne();
for (int i = ; i < ; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(Mutex1Method));
thread.Start(i);
} //为了有时间去启动另外一个进程
Thread.Sleep();
mutex1.ReleaseMutex();
mutex2.ReleaseMutex();
Console.Read();
#endregion
} /// <summary>
/// Mutex1方法
/// </summary>
public static void Mutex1Method(object parameter)
{
mutex1.WaitOne();
Thread.Sleep();
Console.WriteLine("Mutex1:The current value of number is:{0}", ++number);
mutex1.ReleaseMutex();
}
}

第二个进程代码:

    class Program
{
//共享资源
public static int number = ;
//创建对象
public static Mutex mutex2 = new Mutex(false, "Mutex2"); static void Main(string[] args)
{
#region 通过互斥体实现跨进程之间的线程同步
for (int i = ; i < ; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(Mutex2Method));
thread.Start(i);
}
Console.Read();
#endregion
} /// <summary>
/// Mutex2方法
/// </summary>
public static void Mutex2Method(object parameter)
{
mutex2.WaitOne();
Thread.Sleep();
Console.WriteLine("Mutex2:The current value of number is:{0}", ++number);
mutex2.ReleaseMutex();
}
}

运行结果如下:

从结果可以看出,第一个进程的mutex2.ReleaseMutex();信号发出后,第二个进程可以收到并释放线程。

C#线程学习笔记六:线程同步--信号量和互斥体的更多相关文章

  1. JUC源码学习笔记5——线程池,FutureTask,Executor框架源码解析

    JUC源码学习笔记5--线程池,FutureTask,Executor框架源码解析 源码基于JDK8 参考了美团技术博客 https://tech.meituan.com/2020/04/02/jav ...

  2. 操作系统学习笔记----进程/线程模型----Coursera课程笔记

    操作系统学习笔记----进程/线程模型----Coursera课程笔记 进程/线程模型 0. 概述 0.1 进程模型 多道程序设计 进程的概念.进程控制块 进程状态及转换.进程队列 进程控制----进 ...

  3. C#线程学习笔记九:async & await入门二

    一.异步方法返回类型 只能返回3种类型(void.Task和Task<T>). 1.1.void返回类型:调用方法执行异步方法,但又不需要做进一步的交互. class Program { ...

  4. java学习笔记15--多线程编程基础2

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note15.html,转载请注明源地址. 线程的生命周期 1.线程的生命周期 线程从产生到消亡 ...

  5. Linux进程线程学习笔记:运行新程序

    Linux进程线程学习笔记:运行新程序                                         周银辉 在上一篇中我们说到,当启动一个新进程以后,新进程会复制父进程的大部份上下 ...

  6. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  7. Java IO学习笔记六:NIO到多路复用

    作者:Grey 原文地址:Java IO学习笔记六:NIO到多路复用 虽然NIO性能上比BIO要好,参考:Java IO学习笔记五:BIO到NIO 但是NIO也有问题,NIO服务端的示例代码中往往会包 ...

  8. Learning ROS for Robotics Programming Second Edition学习笔记(六) indigo xtion pro live

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  9. Typescript 学习笔记六:接口

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

随机推荐

  1. python3 之 判断闰年小实例

    一.方法1: while True: try: year = int(input('请输入一个年份:')) if (year % 4) == 0 and (year % 100) != 0 or (y ...

  2. nginx支持wss配置

    nginx证书 nginx.conf配置

  3. c# 为什么会出现死锁?多线程死锁怎么解决

    出现死锁必须满足以下几个条件: 1.互斥条件:该进程拥有的资源,其他进程只能等待其释放. 2.不剥夺条件:该进程拥有的资源只能由它自己来释放. 3.请求和保持条件:请求其他的资源,同时自己拥有的资源又 ...

  4. vscode + platformIO开发stm32f4

    我的电脑环境 win10 vscode 1.36.1 vscode安装插件 安装完这个插件后会提示你安装 platformIOCore,按照提示安装即可.安装过程可能比较缓慢, 可能需要翻墙. 新建项 ...

  5. 将String类型转换为int整数类型

    示例如下: public class demo { public static void main(String[] args) { String s="10"; 6 7 //St ...

  6. PAT-2019年秋季考试-甲级

    7-1 Forever (20 分) #include <bits/stdc++.h> using namespace std; int N,K,m,number[10]; multima ...

  7. Android多线程之(一)View.post()源码分析——在子线程中更新UI

    提起View.post(),相信不少童鞋一点都不陌生,它用得最多的有两个功能,使用简便而且实用: 1)在子线程中更新UI.从子线程中切换到主线程更新UI,不需要额外new一个Handler实例来实现. ...

  8. JavaScript的内存模型

    引言 在我们的前端日常工作中,无时无刻不在进行着变量的声明和赋值,你是否也曾碰到过变量声明报错或变量被污染的问题,如果你跟笔者一样碰到过,那么我们应该暂时停下来好好思考问题发生的原因以及如何采取相应的 ...

  9. 一道时间复杂度为O(N)空间复杂度为O(1)的排序问题

    题目:对1, 2, ... , n的一个无序数组,排序,要求时间复杂度为O(N),空间复杂度为O(1). 思路:该题利用数组元素和数组下标相差1的关系,Java代码如下: import java.ut ...

  10. 微服务管理平台nacos虚拟ip负载均衡集群模式搭建

    一.Nacos简介 Nacos是用于微服务管理的平台,其核心功能是服务注册与发现.服务配置管理. Nacos作为服务注册发现组件,可以替换Spring Cloud应用中传统的服务注册于发现组件,如:E ...