信号量与互斥体              

互斥体(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学习笔记的更多相关文章

  1. .NET MVC 学习笔记(六)— 数据导入

    .NET MVC 学习笔记(六)—— 数据导入 在程序使用过程中,有时候需要新增大量数据,这样一条条数据去Add明显不是很友好,这时候最好就是有一个导入功能,导入所需要的数据,下面我们就一起来看一下导 ...

  2. [译]聊聊C#中的泛型的使用(新手勿入) Seaching TreeVIew WPF 可编辑树Ztree的使用(包括对后台数据库的增删改查) 字段和属性的区别 C# 遍历Dictionary并修改其中的Value 学习笔记——异步 程序员常说的「哈希表」是个什么鬼?

    [译]聊聊C#中的泛型的使用(新手勿入)   写在前面 今天忙里偷闲在浏览外文的时候看到一篇讲C#中泛型的使用的文章,因此加上本人的理解以及四级没过的英语水平斗胆给大伙进行了翻译,当然在翻译的过程中发 ...

  3. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  4. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  5. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  6. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  7. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  8. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  9. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

随机推荐

  1. Roman Numeral Converter

    将给定的数字转换成罗马数字. 所有返回的 罗马数字 都应该是大写形式. 这是一些对你有帮助的资源: Roman Numerals Array.splice() Array.indexOf() Arra ...

  2. bzoj2241

    题解: 暴力枚举锤子大小 然后前缀和判断是否可行 代码: #include<bits/stdc++.h> #define N 105 using namespace std; int m, ...

  3. SQL语句中各个部分的执行顺序(转)

    原文链接:http://www.tuicool.com/articles/fERNv2 写在前面的话:有时不理解SQL语句各个部分执行顺序,导致理解上出现偏差,或者是书写SQL语句时随心所欲,所以有必 ...

  4. Ubuntu12.04 中文输入法设置

    1.ibus输入法 Ubuntu系统安装后已经自带了ibus输入法,在英语环境下默认不启动. 配置ibus自动启动可 以在ubuntu系统菜单上选择System(系统)--- Preferences( ...

  5. JS跨页面或跨JS文件对变量赋值

    JS跨页面或跨JS文件对变量赋值,这是很小的一个问题. 但问题虽小,却总觉得有点不够自然,不爽. 为什么呢?访问一个页面上的变量不是什么难事,比如用parent.变量名,或者windows名.变量名, ...

  6. Unity3D 海水多线程渲染算法实现

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...

  7. c++语言第二次作业

    一题目7-1统计学生成绩 1实验代码 #include<stdio.h> int main(void) { int i,n,grade,A,B,C,D,E; A=B=C=D=E=; sca ...

  8. sqlserver获取代理服务作业job的执行情况

    以下脚本为获取sqlserver的执行job with testtemp as( SELECT sch.job_id,--his.[server] as InstanceName CONVERT(nv ...

  9. java sundry tips

    1.关于Arrays 记得binarySearch方法返回的int 类型的数值的含义.    If the array contains multiple elements with the spec ...

  10. C/C++比较容易搞混的一些写法

    #include <stdio.h> int main() { int a = 101; char ch = *(char *)&a; //*(char *)&a:含义就是 ...