이 에세이 계속: .NET 동기화 및 비동기 스레드로부터 안전한 컬렉션(11)
이 에세이와 다음 두 에세이에서는 .NET 동기화 및 비동기 시리즈의 마지막 주요 부분을 소개합니다. : WaitHandle 제품군.
추상 기본 클래스: WaitHandle, 세 개의 하위 클래스: EventWaitHandle(이벤트 알림), Mutex(프로세스 동기화 잠금), Semaphone(세마포) 및 두 개의 하위 클래스: System.Threading.AutoResetEvent, Threading.ManualResetEvent는 모두입니다. EventWaitHandle의 하위 클래스입니다.
[ComVisibleAttribute(true)]public abstract class WaitHandle : MarshalByRefObject, IDisposable
위 정보를 통해 WaitHandle이 MarshalByRefObject를 상속하고 IDisposable 인터페이스를 구현한다는 것을 알 수 있습니다.
당신은 MarshalByRefObject에 대해 잘 알지 못할 수도 있지만 확실히 그 하위 클래스를 많이 사용해 본 적이 있을 것입니다.
MarshalByRefObject는 MSND에서 다음과 같이 설명됩니다.
응용 프로그램 도메인은 운영 체제 프로세스에 하나 이상의 응용 프로그램이 상주하는 파티션입니다. 동일한 애플리케이션 도메인의 개체는 직접 통신합니다. 서로 다른 애플리케이션 도메인의 개체는 애플리케이션 도메인 경계를 넘어 개체 복사본을 전송하거나 프록시를 사용하여 메시지를 교환하는 두 가지 방법으로 통신할 수 있습니다. MarshalByRefObject는 프록시를 사용하여 메시지를 교환하여 애플리케이션 도메인 경계를 넘어 통신하는 객체의 기본 클래스입니다.
이것을 보고 더 혼란스러울 수도 있습니다. 하위 클래스를 사용했나요? 맞습니다. 하위 클래스가 사용되었으며 더 많은 하위 클래스가 있습니다.
예를 들어 System. Drawing 네임스페이스에는 Brush, Image, Pen, Font 등이 있고 System.IO 네임스페이스에는 더 친숙한 Stream도 있습니다.
더 읽어보기: MarshalByRefObject를 사용하여 AOP를 구현합니다.
이를 보면 WaitHandle에 애플리케이션 도메인 간 통신 기능이 있다는 것만 알면 됩니다.
반면, Monitor는 일반적으로 애플리케이션 도메인의 스레드 간 통신에만 사용됩니다. 실제로 잠금에 사용된 개체가 MarshalByRefObject에서 파생된 경우 Monitor는 여러 응용 프로그램 도메인에 잠금을 제공할 수도 있습니다.
Mutex는 운영체제 리소스를 호출해야 하기 때문에 실행 오버헤드가 Monitor보다 훨씬 큽니다. 따라서 애플리케이션 내 스레드 간 작업 동기화만 필요한 경우 모니터/잠금을 먼저 선택해야 합니다.
WaitOne() /WaitOne(TimeSpan, Boolean) 및 여러 오버로드: 소유권을 요청합니다. 이 호출은 현재 뮤텍스가 신호를 받을 때까지 차단됩니다. 선택적 시간 초과 간격에 도달하면 이러한 메서드 중 어느 것도 추가 매개 변수로 잠금 개체를 제공할 필요가 없습니다.
WaitHandle.WaitOne 메서드를 사용하여 뮤텍스 소유권을 요청할 수 있습니다. 호출 스레드는 다음 중 하나가 발생할 때까지 차단됩니다.
뮤텍스는 소유권이 없음을 나타냅니다. 이 경우 WaitOne 메서드는 true를 반환하여 호출 스레드의 뮤텍스 소유권을 가져오고 뮤텍스로 보호되는 리소스에 액세스합니다. 스레드가 리소스 액세스를 완료한 후 ReleaseMutex 메서드를 호출하여 뮤텍스 소유권을 해제해야 합니다.
에 millisecondsTimeout 메소드 또는 timeout 매개변수가 전달되었습니다. . 이 경우 WaitOne 메서드는 false를 반환하며 스레드는 현재 뮤텍스의 소유권을 가져오지 않습니다.
ReleaseMutex(): 현재 Mutex를 한 번 해제합니다. 뮤텍스를 소유한 스레드는 실행을 차단하지 않고 WaitOne 시리즈 함수를 반복적으로 호출할 수 있기 때문에 이 점을 한 번 강조하고 모니터의 Enter()/Exit()는 객체 잠금을 획득한 후 반복적으로 호출할 수 있습니다. Mutex가 호출되는 횟수는 CLR(공용 언어 런타임)에 의해 저장됩니다. 이 횟수는 각 WaitOne()에 대해 +1이고 이 횟수가 0이 아닌 한 다른 Mutex 대기자는 -1입니다. 이 Mutex를 고려하십시오. 해제되지 않으면 Mutex를 얻을 수 있는 방법이 없습니다. 또한 Monitor.Exit()와 마찬가지로 Mutex의 소유자만 RleaseMutex()를 수행할 수 있습니다. 그렇지 않으면 예외가 발생합니다.
뮤텍스를 소유한 상태에서 스레드가 종료되면 뮤텍스가 포기되었다고 합니다. MSDN에서 Microsoft는 이것이 "심각한" 프로그래밍 오류라고 경고합니다. 이는 뮤텍스의 소유자가 소유권을 얻은 후 WaitOne() 및 ReleaseMutex()의 수가 동일하지 않고 호출자 자체가 무책임하게 종료되어 뮤텍스에 의해 보호되는 리소스가 일관되지 않은 상태가 된다는 것을 의미합니다. 실제로 이는 try/finally 구조에서 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访问的安全性控制。
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에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!