本随笔续接:.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. JavaEE 之 log4j

    1.log4j a.概念:一个非常优秀的开源日志记录工具 b.配置: ①src同目录下建立log4j.properties文件,书写: log4j.rootLogger=debug,appender1 ...

  2. hexo添加404公益界面

    http://hellolb.top/2018/08/16/hexo添加404公益界面/ hexo个人博客添加404公益界面,这里我使用的腾讯404公益界面 我的博客主题是hexo+yilia,其实所 ...

  3. POJ 2352 Stars【树状数组】

    <题目链接> 题目大意: 题目给出n个点,这些点按照y坐标的升序,若y相同,则按照x的升序顺序输入,问,在这些点中,左下角的点的数量分别在0~n-1的点分别有多少个,写出它们的对应点数. ...

  4. raid 搭建

    RAID几种常见的类型 RAID类型 最低磁盘个数 空间利用率 各自的优缺点 级 别 说 明 RAID0 条带卷 2+ 100% 读写速度快,不容错 RAID1 镜像卷 2 50% 读写速度一般,容错 ...

  5. Python实现的各种机器学习算法

    七种算法包括: 线性回归算法 Logistic 回归算法 感知器 K 最近邻算法 K 均值聚类算法 含单隐层的神经网络 多项式的 Logistic 回归算法 01 线性回归算法 在线性回归中,我们想要 ...

  6. Mysql建库建用户建表等常用命令

    格式: mysql -h主机地址 -u用户名 -p用户密码 1.连接到本机上的MYSQL.首先打开DOS窗口,然后进入目录mysql\bin,再键入命令mysql -u root -p,回车后提示你输 ...

  7. (转)java程序员进入名企需要掌握哪些,立一个flag

    想要成为合格的Java程序员或工程师到底需要具备哪些专业技能,在面试之前到底需要准备哪些东西呢?面试时面试官想了解你的什么专业技能,以下都是一个合格Java软件工程师所要具备的. 一.专业技能 熟练的 ...

  8. sqlserver触发器insert,delete,update

    Create Trigger [dbo].[upemployee_kefyu_sale] on [dbo].[employee] for update as if update(FullName) b ...

  9. 使用itchat实现一个微信机器人聊天回复功能

    近看到好多群里都有一个@机器人的功能,挺有趣的,想自己也玩下,就通过百度一点点实现,在这总结一下整个从无到有的过程. 首先,要知道itchat,它是Python写的,所以想要实现这个机器人的功能,需要 ...

  10. flask内容

    Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后 ...