本随笔续接:.NET 同步与异步 之 线程安全的集合 (十一)

本随笔 及 接下来的两篇随笔,将介绍 .NET 同步与异步系列 的最后一个大块知识点:WaitHandle家族。

抽象基类:WaitHandle, 三个子类: EventWaitHandle(Event通知) 、Mutex(进程同步锁)、Semaphone (信号量),还有两个孙子辈:System.Threading.AutoResetEventSystem.Threading.ManualResetEvent,都是 EventWaitHandle 的子类。

一、抽象基类 WaitHandle

[ComVisibleAttribute(true)]
public abstract class WaitHandle : MarshalByRefObject, IDisposable

通过上面的信息,我们可以知道 WaitHandle  继承自 MarshalByRefObject, 并实现了 IDisposable 接口。

对于 MarshalByRefObject,你也许不是很熟悉,但它的很多子类你一定会用过的,让我们来揭开它的庐山真面目。

在MSND中是这样描述 MarshalByRefObject 的:

应用程序域是一个操作系统进程中一个或多个应用程序所驻留的分区。同一应用程序域中的对象直接通信。不同应用程序域中的对象的通信方式有两种:一种是跨应用程序域边界传输对象副本,一种是使用代理交换消息。MarshalByRefObject 是通过使用代理交换消息来跨应用程序域边界进行通信的对象的基类。

看到这里你也许更迷惑了,我用过它? 用过它的子类? 没错,就是用过它的子类,并且还很多。

例如 System.Drawing命名空间的 Brush、Image、Pen、Font 等等,还有个大家更熟悉的 System.IO命名空间下的Stream.

延展阅读:利用 MarshalByRefObject 实现 AOP

看到这里我们只需要知道 WaitHandle 具有跨应用程序域进行通讯的能力就可以了。

二、Mutex(进程同步锁)

1、MSDN对Mutex的定义为进程间的同步基元, 即锁的概念。

  反观Monitor、平时只用来在应用程序域内的线程之间通信。其实,如果用于锁的对象派生自MarshalByRefObject,Monitor 也可在多个应用程序域中提供锁定。

  Mutex由于需要调用操作系统资源,因此执行的开销比Monitor大得多,所以如果仅仅需要在应用程序内部的线程间同步操作,Monitor/lock应当是首选

2、Mutex 的用法

  • WaitOne() /WaitOne(TimeSpan, Boolean)及若干个重载:请求所有权,该调用会一直阻塞到当前 mutex 收到信号,或直至达到可选的超时间隔,这几个方法都不需要提供锁定对象作为额外参数。

    • 您可以使用 WaitHandle.WaitOne 请求所有权的互斥体的方法。 调用线程受到阻止,直到发生下列情况之一︰
    • 互斥体发出信号以指示不拥有。 在此情况下, WaitOne 方法将返回 true, ,调用线程的互斥体所有权,并访问由 mutex 保护的资源。 线程完成后访问资源,必须调用 ReleaseMutex 方法来释放 mutex 的所有权。

    • 对调用中指定的超时间隔 WaitOne 具有方法 millisecondsTimeout 或 timeout 参数已过。 在此情况下, WaitOne 方法将返回 false, 此时该线程不会获取互斥体的所有权。

  • ReleaseMutex():释放当前 Mutex 一次。注意,这里强调了一次,因为拥有互斥体的线程可以在重复的调用WaitOne系列函数而不会阻止其执行;这个跟Monitor的Enter()/Exit()可以在获取对象锁后可以被重复调用一样。Mutex被调用的次数由公共语言运行库(CLR)保存,每WaitOne()一次计数+1,每ReleaseMutex()一次计数-1,只要这个计数不为0,其它Mutex的等待者就会认为这个Mutex没有被释放,也就没有办法获得该Mutex。 另外,跟Monitor.Exit()一样,只有Mutex的拥有者才能RleaseMutex(),否则会引发异常。
  • 如果线程在拥有互斥体时终止,我们称此互斥体被遗弃(Abandoned)。在MSDN里,微软以警告的方式指出这属于“严重的”编程错误。这是说拥有mutex的拥有者在获得所有权后,WaitOne()和RelaseMutex()的次数不对等,调用者自身又不负责任地中止,造成mutex 正在保护的资源可能会处于不一致的状态。其实,这无非就是提醒你记得在try/finally结构中使用Mutex

3、全局和局部的Mutex

如果在一个应用程序域内使用Mutex,当然不如直接使用Monitor/lock更为合适,因为前面已经提到Mutex需要更大的开销而执行较慢。不过Mutex毕竟不是Monitor/lock,它生来应用的场景就应该是用于进程间同步的。用于在进程间通讯的Mutex我们称为全局Mutex,而只用于在应用程序域内部通讯的Mutex、我们称为局部Mutex.

全局Mutex和局部Mutex是通过构造函数来构造不同的实例的,让我们来看一下Mutex的构造函数,一共有5个,挑两个具有代表性的看一下吧:

  • Mutex():用无参数的构造函数得到的Mutex没有任何名称,而进程间无法通过变量的形式共享数据,所以没有名称的Mutex也叫做局部(Local)Mutex。另外,这样创建出的Mutex,创建者对这个实例并没有拥有权,仍然需要调用WaitOne()去请求所有权。
  • Mutex(Boolean initiallyOwned, String name, out Booldan createdNew, MutexSecurity):第一个bool参数:指示初始化的实例是否拥有互斥体所有权。第二个string类型、为互斥体指定一个名称,如果string为null或者空字符串 则相当于创建一个没有名字的Mutex,当属于局部Mutex. 而有名字的Mutex当属于全局Mutex.第三个bool参数、如果已经初始化了互斥体 返回True, 如果互斥体已经存在则返回False. 最后一个参数用于Mutex访问的安全性控制。

4、用途

Mutex天生为进程间的同步基元,因此它可以用来控制应用程序的单实例

/// <summary>
/// 单实例运行
/// </summary>
/// <returns> true 应用程序已启动,false 则没有 </returns>
public bool SingleRun(ref System.Threading.Mutex mutex )
{
mutex = new System.Threading.Mutex(false, "WINDOWS");
if (!mutex.WaitOne(, false))
{
mutex.Close();
mutex = null;
}
if (mutex == null)
{
return true;
}
return false;
}

进程单实例

未完待续,下一篇随笔: EventWaitHandle(Event通知)

附,Demo : http://files.cnblogs.com/files/08shiyan/ParallelDemo.zip

参见更多:随笔导读:同步与异步

.NET 同步与异步 之 Mutex (十二)的更多相关文章

  1. .NET 同步与异步 之 EventWaitHandle(Event通知) (十三)

    本随笔续接:.NET 同步与异步 之 Mutex (十二) 在前一篇我们已经提到过Mutex和本篇的主角们直接或间接继承自 WaitHandle: Mutex类,这个我们在上一篇已经讲过. Event ...

  2. Gradle 1.12用户指南翻译——第三十二章. JDepend 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  3. Gradle 1.12用户指南翻译——第四十二章. Announce插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  4. SpringBoot第十二集:度量指标监控与异步调用(2020最新最易懂)

    SpringBoot第十二集:度量指标监控与异步调用(2020最新最易懂) Spring Boot Actuator是spring boot项目一个监控模块,提供了很多原生的端点,包含了对应用系统的自 ...

  5. java 轻量级同步volatile关键字简介与可见性有序性与synchronized区别 多线程中篇(十二)

    概念 JMM规范解决了线程安全的问题,主要三个方面:原子性.可见性.有序性,借助于synchronized关键字体现,可以有效地保障线程安全(前提是你正确运用) 之前说过,这三个特性并不一定需要全部同 ...

  6. .NET 同步与异步 之 警惕闭包(十)

    本随笔续接:.NET 同步与异步 之 原子操作和自旋锁(Interlocked.SpinLock)(九) 至此.同步与异步 相关的常规操作(比较常见的操作).差不多已经介绍完毕. 本随笔就着重说一下闭 ...

  7. {python之协程}一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二

    python之协程 阅读目录 一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二 一 引子 本 ...

  8. python学习笔记-(十四)I/O多路复用 阻塞、非阻塞、同步、异步

    1. 概念说明 1.1 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心是内核,独立于普通的应用程序,可 ...

  9. Scrapy基础(十二)————异步导出Item数据到Mysql中

    异步导出数据到Mysql中 上次说过从Item中同步写入数据库,因为网络的下载速度和数据库的I/O速度是不一样的所以有可能会发生下载快,但是写入数据库速度慢,造成线程的堵塞:关于堵塞和非堵塞,同步和异 ...

随机推荐

  1. Full Tank? POJ - 3635 (bfs | 最短路)

    After going through the receipts from your car trip through Europe this summer, you realised that th ...

  2. JVM之浮点数(float)表示

    1. 浮点数的组成:符号位.指数位.尾数位. 1.1 符号位: 占1位,表示正负数: 1.2 指数位: 占8位: 1.3 尾数位: 占23位. 2.  浮点数的表示: 2.1 取值: sflag * ...

  3. shell编程第三天

  4. SpringBoot的国际化使用

    在项目中,很多时候需要国际化的支持,这篇文章要介绍一下springboot项目中国际化的使用. 在这个项目中前端页面使用的thymeleaf,另外加入了nekohtml去掉html严格校验,如果不了解 ...

  5. 在notepad++中修改换行符

    在notepad++中编辑时,将按tab键设置为插入4个空格而不是tab字符

  6. 发布网站配置IIS(把网上找到的解决方法综合了一下)

    1.由于权限不足而无法读取配置文件,无法访问请求的页面(参考网址:http://blog.csdn.net/yinjingjing198808/article/details/7185453) 2.处 ...

  7. BZOJ.2726.[SDOI2012]任务安排(DP 斜率优化)

    题目链接 数据范围在这:https://lydsy.com/JudgeOnline/wttl/thread.php?tid=613, 另外是\(n\leq3\times10^5\). 用\(t_i\) ...

  8. ironic驱动-IMPITool

    概述 IMPITool驱动是通过ipmitool工具来管理部署节点的,目前主要有两个驱动: agent_ipmitool pxe_ipmitool 配置驱动 要修改ironic支持的驱动需要修改配置文 ...

  9. JAVA笔记--static

    1.static 修饰变量 public class MyClass { static int i = 4; } 其中static 修饰变量,表示变量 i 属于 MyClass 类,所有的对象共享一个 ...

  10. 通过xml处理sql语句时对小于号与大于号的处理转换

    以上方法,很容易使用,直接ss < #{ss} 法二   <![CDATA[>=]]>表示大于等于      变量<![CDATA[ < ]]>#{变量}表示 ...