WaitHandle学习笔记
信号量与互斥体
互斥体(Mutex)是操作系统中一种独占访问共享资源的机制。它像一把所锁,哪个线程获取到互斥体的控制权,则可以访问共享的资源,或者执行处于受保护的代码。而其他的线程如果也想获取控制权,则需要要阻塞等待,知道拥有控制权的线程释放控制权。
信号量(Semaphore)是操作系统中协调多个线程访问共享资源的机制。他内部维护一个非负整数计数器。0表示不能再接受更多的共享访问请求,大于零的数值X表示最多还能接受X个线程的共享访问请求。而非负整数的操作只能通过wait()或者signal()来进行原子操作。signal将计数器加1; wait()将计数器减1,如果当前值为0则阻塞知道有其他线程调用signal。通过这种机制来实现最多X个线程访问共享资源。这种机制通常可以用来解决生产者和消费者问题。(假如产品队列最多能装X个产品,生产者相当于wait操作,消费者相当于signal操作)
.NET 中的WaitHandle

在.Net Framework中有上图中三个子类。用来表示操作系统中的互斥体和信号量。
Mutex
Mutex是对操作系统中互斥体的包装,可以创建未命名的本地Mutex(只在当前进程有效),也可以创建命名的全局Mutex(操作系统有效,跨进程)。具体操作如下:
var _mutex = new Mutex(false);
new Task(() =>
{
_mutex.WaitOne();//获取mutex控制权
Console.WriteLine("Got mutex signal. Thread Id:1");
Thread.Sleep();
_mutex.ReleaseMutex();//释放mutex控制权
Console.WriteLine("Release mutex signal, Thread Id:1");
}).Start(); new Task(() =>
{
_mutex.WaitOne();//获取mutex控制权,在thread 1释放之前,该调用会阻塞
Console.WriteLine("Got mutex signal Thread id:2");
Thread.Sleep();
_mutex.ReleaseMutex();
Console.WriteLine("Release mutex signal, Thread Id:2"); }).Start();
在操作Mutex时,系统会检查Thread Identity,只有获取Mutex控制权的线程才能释放控制权。
Semaphore
Semaphore是对操作系统中信号量的包装,同样也可以创建未命名的Semaphore(只在当前进程有效)和命名的全局Semaphore(操作系统有效,跨进程)具体操作如下:
但是在操作Semaphore时,和Mutex不一样,系统不会检查Thread Identity。任何线程都可以对Semaphore进行WaitOne()和Release()
var _semaphore = new Semaphore(, );//设置最大允许访问共享资源线程数为2
new Task(() =>
{
for (int index = ; index < 3; index++)
{
_semaphore.WaitOne();//第三次调用该方法是会被阻塞,因为计数器为0.当其他线程调用Release后才能继续
Console.WriteLine("Got Semaphore Signal. Thread Id:" + Thread.CurrentThread.ManagedThreadId);
}
}).Start();
new Task(() =>
{
Thread.Sleep();
Console.WriteLine("Release Semaphore, Thread Id:" + Thread.CurrentThread.ManagedThreadId);
_semaphore.Release();//计数器+1
}).Start();
EventWaitHandle
这个类其实提供了和Mutex类似的线程之间同步,通知机制。它也能创建本地WaitHandle和全局WaitHandle。但是和Mutex又有区别:
- 它内部其实维护了一个布尔类型变量来标示当前wait handle是否空闲:true表示空闲,可以被申请控制权; false则表示wait handle已经被线程持有控制权。(当调用WaitOne获取控制权时,如果内部标量为false,则阻塞知道其他线程将其Set为true.)而对该变量的操作只能通过Set()(将变量设为true),Reset()(将变量设为false)来进行原子操作。
- EventWaitHandle并不提供独占操作,当内部变量为true时,所有线程的WaitOne操作都能获取到控制权,而不是只有一个能获取到(通过设置WaitHandle为AutoReset也可以实现)
- 在操作EventWaitHandle时,系统也不会检查Thread Identity
具体操作如下:
var _waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
//这里指定AutoReset类型后,WaitOne调用获取到控制权后会同时将内部变量置为false,相当于调用Reset()
new Task(() =>
{
_waitHandle.WaitOne();
Console.WriteLine("Got the signal, thread id:" + Thread.CurrentThread.ManagedThreadId);
}).Start(); new Task(() =>
{
_waitHandle.WaitOne();
Console.WriteLine("Got the signal, thread id:" + Thread.CurrentThread.ManagedThreadId);
}).Start(); new Task(() =>
{
Console.WriteLine("Set the signal, thread id:" + Thread.CurrentThread.ManagedThreadId);
_waitHandle.Set();
}).Start();
WaitHandle学习笔记的更多相关文章
- .NET MVC 学习笔记(六)— 数据导入
.NET MVC 学习笔记(六)—— 数据导入 在程序使用过程中,有时候需要新增大量数据,这样一条条数据去Add明显不是很友好,这时候最好就是有一个导入功能,导入所需要的数据,下面我们就一起来看一下导 ...
- [译]聊聊C#中的泛型的使用(新手勿入) Seaching TreeVIew WPF 可编辑树Ztree的使用(包括对后台数据库的增删改查) 字段和属性的区别 C# 遍历Dictionary并修改其中的Value 学习笔记——异步 程序员常说的「哈希表」是个什么鬼?
[译]聊聊C#中的泛型的使用(新手勿入) 写在前面 今天忙里偷闲在浏览外文的时候看到一篇讲C#中泛型的使用的文章,因此加上本人的理解以及四级没过的英语水平斗胆给大伙进行了翻译,当然在翻译的过程中发 ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
- 2014年暑假c#学习笔记目录
2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- seaJs学习笔记2 – seaJs组建库的使用
原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...
- CSS学习笔记
CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...
随机推荐
- JavaScript---js的模块化
js的模块模式被定义为给类提供私有和公共封装的一种方法,也就是我们常说的“模块化”. 怎么实现“模块化”? 通过闭包的原理来实现“模块化” ,具体实现:1.必须有外部的封闭函数,该函数必须至少被调用 ...
- linux下面安装maven
maven作为最近比较火的项目管理工具,对项目的jar包及其开元添加相应的插件的管理,很方便. 安装maven: 在官网上面去下载最新的maven的压缩包,apache-maven-3.3.1-bin ...
- C# 处理 JSON 常用的帮助类
C#请求接口的方法,具体代码: 首先需要添加引用和第三方的组件,具体如下: 引用命名空间: using System.IO; using Newtonsoft.Json.Linq; using Sys ...
- 缓存LruCache简单创建和使用
LruCache一般使用: /** * 总容量为当前进程的1/8,单位:KB * sizeOf():计算缓存对象的大小,单位要一致 * entryRemoved():移除旧缓存时调用 */ int m ...
- hdu 6114 chess(排列组合)
Chess Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- elasticsearch关于索引切分的实现
[背景信息] ES一直以来对于已经创建好的索引的分片是不可以进行分割的,简单的说,当你创建了一个索引,并指定了number_of_shards为2,当随着数据量的不断增大,是无法将索引的shard扩充 ...
- Mimiktaz抓取本机密码
Mimiktaz2.0以后的版本只需要两条命令即可实现密码的抓取 mimikatz # privilege::debug mimikatz # sekurlsa::logonpasswords
- 使用JQuery Deferred对象的then() 解决多个AJAX操作顺序依赖的问题
原文地址:http://www.2cto.com/kf/201507/424202.html 之前的文章javascript异步代码的回调地狱中提到了编写AJAX代码经常遇到的3个问题,现在我们看下如 ...
- [AirFlow]AirFlow使用指南四 DAG Operator Task
1. DAG 在Airflow中,DAG或有向无环图是你运行所有任务的集合,以某种组织方式来反映所有任务之间的关系和依赖. 例如,一个简单的DAG可以包括三个任务:A,B和C.可以说A必须在B运行之前 ...
- Android性能优化系列之电量优化
电量消耗的计算与统计是一件麻烦而且矛盾的事情,记录电量消耗本身也是一个费电量的事情,随着Android开的性能要求越来越高,电量的优化,也显得格外重要,一个耗电的应用,用户肯定会毫不犹豫的进行卸载,所 ...