C#线程学习笔记六:线程同步--信号量和互斥体
本笔记摘抄自: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#线程学习笔记六:线程同步--信号量和互斥体的更多相关文章
- JUC源码学习笔记5——线程池,FutureTask,Executor框架源码解析
JUC源码学习笔记5--线程池,FutureTask,Executor框架源码解析 源码基于JDK8 参考了美团技术博客 https://tech.meituan.com/2020/04/02/jav ...
- 操作系统学习笔记----进程/线程模型----Coursera课程笔记
操作系统学习笔记----进程/线程模型----Coursera课程笔记 进程/线程模型 0. 概述 0.1 进程模型 多道程序设计 进程的概念.进程控制块 进程状态及转换.进程队列 进程控制----进 ...
- C#线程学习笔记九:async & await入门二
一.异步方法返回类型 只能返回3种类型(void.Task和Task<T>). 1.1.void返回类型:调用方法执行异步方法,但又不需要做进一步的交互. class Program { ...
- java学习笔记15--多线程编程基础2
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note15.html,转载请注明源地址. 线程的生命周期 1.线程的生命周期 线程从产生到消亡 ...
- Linux进程线程学习笔记:运行新程序
Linux进程线程学习笔记:运行新程序 周银辉 在上一篇中我们说到,当启动一个新进程以后,新进程会复制父进程的大部份上下 ...
- java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)
java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...
- Java IO学习笔记六:NIO到多路复用
作者:Grey 原文地址:Java IO学习笔记六:NIO到多路复用 虽然NIO性能上比BIO要好,参考:Java IO学习笔记五:BIO到NIO 但是NIO也有问题,NIO服务端的示例代码中往往会包 ...
- Learning ROS for Robotics Programming Second Edition学习笔记(六) indigo xtion pro live
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...
- Typescript 学习笔记六:接口
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
随机推荐
- vue computed计算属性 watch监听
计算属性 computed:{ 变量:function(){ return 计算好的值 } } 这时候计算好的值 就付给了你的变量 在实例中可以this.使用 注意 声明的变量的data中不可以重复声 ...
- C# 8.0的计划特性
虽然现在C# 7才发布不久,并且新的版本和特性还在增加中,但是C# 8.0已经为大家公开了一些未来可能出现的新特性. *注:以下特性只是计划,可能在将来的正式版本会有一些差异 1.Nullable R ...
- CentOS7中安装MariaDB
什么是mariaDB? 在线安装(慢的要命) RPM离线安装(CentOS7.X) 在线安装 打开官方网站 https://mariadb.org/ 点击Download,跳转到下一页面 继续点击Do ...
- 使用RNN进行imdb影评情感识别--use RNN to sentiment analysis
原创帖子,转载请说明出处 一.RNN神经网络结构 RNN隐藏层神经元的连接方式和普通神经网路的连接方式有一个非常明显的区别,就是同一层的神经元的输出也成为了这一层神经元的输入.当然同一时刻的输出是不可 ...
- 【NHOI2018】跳伞登山赛
[题目描述] 某山区有高高低低的 n 个山峰,根据海拔高度的不同,这些山峰由低到高进行了 1 到 n 编号.有 m 条只能单向通行的羊肠小道连接这些山峰.现在,这里要举行一场跳伞登山赛,选手们伞降到某 ...
- yum运行报错:File "/usr/bin/yum", line 30 except KeyboardInterrupt, e: ^SyntaxError: invalid syntax
这是由于Python升级导致 备份Python 历史版本 [root@sdw1 autoconf]# ls /usr/bin/python* [root@sdw1 autoconf]# mv /usr ...
- 2019牛客暑期多校训练营(第九场) E All men are brothers
传送门 知识点:并查集+组合数学 并查集合并操作可以理解为使得两个集合的人互相成为朋友,也就是两个集合并在了一起,答案是要求从所有人中挑出四个互相不是朋友的四个人,比较基础的组合数学知识,但因为每个集 ...
- 100天搞定机器学习|Day57 Adaboost知识手册(理论篇)
Boosting算法 Boosting是一种用来提高弱分类器准确度的算法,是将"弱学习算法"提升为"强学习算法"的过程,主要思想是"三个臭皮匠顶个诸葛 ...
- 【RN - 基础】之Image使用简介
Image组件是用来加载图片的.React Native项目加载图片往往有三种方式: 从React Native项目中加载图片: 从APP项目中加载图片: 从网络中加载图片. Image组件加载图片 ...
- FBV与CBV 及CBV源码分析
FBV与CBV 及CBV源码分析 FBV(Function Based View) 基于函数的视图 基于函数的视图,我们一直在用没啥好讲的,就是导入模块调用函数执行业务 CBV(Class Based ...