信号量与互斥体              

互斥体(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. 数论基础算法总结(python版)

    /* Author: wsnpyo Update Date: 2014-11-16 Algorithm: 快速幂/Fermat, Solovay_Stassen, Miller-Rabin素性检验/E ...

  2. Ansible 小手册系列 十七(特性模块)

    异步操作和轮询 --- # Requires ansible 1.8+ - name: 'YUM - fire and forget task' yum: name=docker-io state=i ...

  3. KMP算法(改进后的字符串匹配算法)

    转载:http://blog.csdn.net/liu88010988/article/details/50789960 kmp算法完成的任务是:给定两个字符串O和f,长度分别为n和m,判断f是否在O ...

  4. vue router使用query和params传参的使用

    传参是前端经常需要用的一个操作,很多场景都会需要用到上个页面的参数,本文将会详细介绍vue router 是如何进行传参的,以及一些小细节问题.有需要的朋友可以做一下参考,希望可以帮到大家. Vue ...

  5. 转:基于Flume的美团日志收集系统(一)架构和设计

    美团的日志收集系统负责美团的所有业务日志的收集,并分别给Hadoop平台提供离线数据和Storm平台提供实时数据流.美团的日志收集系统基于Flume设计和搭建而成. <基于Flume的美团日志收 ...

  6. Android_布局属性大全

    RelativeLayout 第一类:属性值为true可false android:layout_centerHrizontal        水平居中 android:layout_centerVe ...

  7. Github上的iOS App源码 (中文)

    Github版英文App地址 中文 : TeamTalk 蘑菇街. 开源IM. 电商强烈推荐. MyOne-iOS 用OC写的<一个> iOS 客户端 zhihuDaily 高仿知乎日报 ...

  8. VPS安装metasploit-framework

    一.安装过程 在/etc/apt/sources.list添加kali源: root@localhost:~# cat >> /etc/apt/sources.list <<  ...

  9. .net的session详解

    http://blog.csdn.net/justin_wkf/article/details/5746914#comments

  10. 如何预编译ASP.Net程序

    打开Developer Command Prompt,执行命令 aspnet_compiler -v \Target  -p 源文件夹地址 -f 目标文件夹地址