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 ...
随机推荐
- Ubuntu下压缩解压文件
一般来说ubuntu 下带有tar 命令,可以用来解压和压缩之用.但是我们经常要与win下用户打交道,所以要安装一些解压工具如:rar zip 等命令. 如果要需要用到zip工具那么可以: sudo ...
- Neutron之OVS
OVS即开放虚拟交换标准,不仅仅是为了支持OpenFlow协议,而是为了给虚拟化平台上运行的虚拟机实例提供一套纯软件实现的路由交换协议栈.具体点说,Open vSwitch是在开源的Apache2.0 ...
- Linux 挂载系统盘
适用系统:非IO优化+SSD云盘Linux(Redhat , CentOS,Debian,Ubuntu)实例,IO优化实例+SSD云盘数据盘分区挂载建议使用脚本:工具:auto_fdisk_ssd.s ...
- 【51nod-1396】还是01串
给定一个0-1串s,长度为n,下标从0开始,求一个位置k,满足0<=k<=n, 并且子串s[0..k - 1]中的0的个数与子串s[k..n - 1]中1的个数相等. 注意: (1) 如果 ...
- python中time()时间的相关问题
Python中time模块详解(转) 在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time ...
- 进程与网络监控和ssh简单使用
进程的概念和管理 进程: 正在执行的程序 线程: 轻量级的进程 进程有独立的地址空间,线程没有 线程不能独立存在,它是由进程创建.Thread1.在linux中,每个执行的程序都称为一个进程.每一个进 ...
- web服务器无法显示font-awesome字体图标
今天遇到了在本地运行网页 一切调用的额font的小图标都OK的,但是把网页发布到tomcat服务器上面就不行了 之后百度了下,找到了解决方法,遂记录下,方法如下: 在web.xml 文件中加上: &l ...
- C++面向对象高级编程(六)转换函数与non-explicit one argument ctor
技术在于交流.沟通,转载请注明出处并保持作品的完整性. 1.conversion function 转换函数 //1.转换函数 //conversion function //只要你认为合理 你可以任 ...
- C语言 运算符详细介绍及示例代码
C 运算符 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号.C 语言内置了丰富的运算符,并提供了以下类型的运算符: 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 杂项运算符 本章将逐 ...
- VM遇到的问题参考
http://saturn.blog.51cto.com/184463/950731/