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 中 keep-alive 缓存数据、离开时位置
路由中: 页面中: 需要缓存的组件中: 因为是keep-alive 所以在初始化页面的时候 会走一次生命周期 当二次进入的时候就已经是缓存状态了 不会在走生命周期 于是它就有了自己的周期函数分别是 ...
- 【2018寒假集训 Day2】【动态规划】钱币兑换(exchange)(自己翻译的2333)
钱币兑换(exchange) 问题描述: Dave偶然获得了未来几天的美元(dollars)与马克(marks)之间的兑换率.例如Dave开始有100marks,请编写个程序帮助Dave找出最好的买卖 ...
- http_web_cache
HTTP Web Cache 程序资源的访问具有局部性 时间局部性:一个被访问过的资源很有可能在近期被再次访问. 空间局部性:一个被访问过的资源,它的周边资源很有可能被访问到. 如何衡量缓存的有效性? ...
- 防范XSS攻击
原文链接:http://www.cnblogs.com/chenty/p/5136834.html 最近,有个项目突然接到总部的安全漏洞报告,查看后知道是XSS攻击. 问题描述: 在页面上有个隐藏域: ...
- 阿里云上万个 Kubernetes 集群大规模管理实践
点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 汤志敏,阿里 ...
- rsync工具、rsync常用选项、以及rsync通过ssh同步 使用介绍
第8周5月14日任务 课程内容: 10.28 rsync工具介绍10.29/10.30 rsync常用选项10.31 rsync通过ssh同步 10.28 rsync工具介绍 rsync是一个同步的工 ...
- lvm_lv_extend
根分区lv扩容 xfs格式 neokylinV7.0 [root@localhost ~]# fdisk /dev/vda 欢迎使用 fdisk (util-linux 2.23.2). 更改将停留在 ...
- 输入URL按下enter键后发生的事
输入URL按下enter键后浏览器和服务器各自发生的事. 浏览器 1.用户在浏览器中输入URL地址 2.浏览器解析用户输入的URL地址=>域名+端口 3.浏览器检查本地缓存中是否存在这个域名=& ...
- 服务容错保护hystrix
灾难性雪崩效应 如何解决灾难性雪崩效应 降级 超时降级.资源不足时(线程或信号量)降级,降级后可以配合降级接口返回托底数据.实现一个 fallback 方法, 当请求后端服务出现异常的时候, 可以使用 ...
- Spring Boot结和Spring Data(Ehcache缓存,Thymeleaf页面,自定义异常页面跳转,Swagger2)
项目结构 pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...