本随笔续接:.NET 同步与异步 之 线程安全的集合 (十一)
本随笔 及 接下来的两篇随笔,将介绍 .NET 同步与异步系列 的最后一个大块知识点:WaitHandle家族。
抽象基类:WaitHandle, 三个子类: EventWaitHandle(Event通知) 、Mutex(进程同步锁)、Semaphone (信号量),还有两个孙子辈:System.Threading.AutoResetEvent、System.Threading.ManualResetEvent,都是 EventWaitHandle 的子类。
[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 具有跨应用程序域进行通讯的能力就可以了。
反观Monitor、平时只用来在应用程序域内的线程之间通信。其实,如果用于锁的对象派生自MarshalByRefObject,Monitor 也可在多个应用程序域中提供锁定。
Mutex由于需要调用操作系统资源,因此执行的开销比Monitor大得多,所以如果仅仅需要在应用程序内部的线程间同步操作,Monitor/lock应当是首选
互斥体发出信号以指示不拥有。 在此情况下, WaitOne 方法将返回 true, ,调用线程的互斥体所有权,并访问由 mutex 保护的资源。has finished accessing the resource, the thread must call the <span class="mtpsTagOuterHtml" >ReleaseMutex method to release ownership of the mutex."> 线程完成后访问资源,必须调用 ReleaseMutex 方法来释放 mutex 的所有权。
对调用中指定的超时间隔 WaitOne 具有方法 millisecondsTimeout 或 timeout 参数已过。 在此情况下, WaitOne 方法将返回 false, 此时该线程不会获取互斥体的所有权。
如果在一个应用程序域内使用Mutex,当然不如直接使用Monitor/lock更为合适,因为前面已经提到Mutex需要更大的开销而执行较慢。不过Mutex毕竟不是Monitor/lock,它生来应用的场景就应该是用于进程间同步的。用于在进程间通讯的Mutex我们称为全局Mutex,而只用于在应用程序域内部通讯的Mutex、我们称为局部Mutex.
全局Mutex和局部Mutex是通过构造函数来构造不同的实例的,让我们来看一下Mutex的构造函数,一共有5个,挑两个具有代表性的看一下吧:
Mutex天生为进程间的同步基元,因此它可以用来控制应用程序的单实例:
logs_code_hide('f8e0e18b-f892-4dd0-a9e4-ef0ed061b5b7',event)" src="/Upload/Images/2017032205/2B1B950FA3DF188F.gif" alt="" />/// <summary> /// 单实例运行 /// </summary> /// <returns> true 应用程序已启动,false 则没有 </returns> public bool SingleRun(ref System.Threading.Mutex mutex ) { mutex = new System.Threading.Mutex(false, "WINDOWS"); if (!mutex.WaitOne(0, false)) { mutex.Close(); mutex = null; } if (mutex == null) { return true; } return false; }进程单实例
未完待续,下一篇随笔: EventWaitHandle(Event通知)
附,Demo : http://files.cnblogs.com/files/08shiyan/ParallelDemo.zip
参见更多:随笔导读:同步与异步