本漫笔 及 接下来的两篇漫笔,将引见 .NET 同步与异步系列 的末了一个大块知识点:WaitHandle家属。
笼统基类:WaitHandle, 三个子类: EventWaitHandle(Event关照) 、Mutex(历程同步锁)、Semaphone (信号量),另有两个孙子辈:System.Threading.AutoResetEvent、System.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(0, false)) { mutex.Close(); mutex = null; } if (mutex == null) { return true; } return false; }
以上就是详解.NET 同步与异步 之 Mutex的细致内容,更多请关注ki4网别的相干文章!