【Windows】線程漫談——.NET線程同步之Event和Mutex


本系列意在記錄Windwos線程的相關知識點,包括線程基礎、線程調度、線程同步、TLS、線程池等

本篇介紹與內核對象同步相關的Event對象和Mutex對象

 

AutoResetEvent和ManualResetEvent

同步事件有兩種:AutoResetEvent和 ManualResetEvent。主要用戶線程之間的通知,實現同步。無論是哪種,實際上是每個Event對象關聯了一個事件內核對象。在【Windows】線程漫談——線程同步之等待函數和事件內核對象中,詳細介紹了事件內核對象和等待函數。.NET這里的兩個版本是對它們的封裝。下面簡單回顧一下事件內核對象:

事件內核對象有兩種狀態:觸發狀態、非觸發狀態。等待函數用來檢測某種內核對象的狀態,當鎖檢測的內核對象是觸發狀態的時候等待函數將直接返回,否則將阻塞。(這樣的表述其實是不完整的,這里只是簡單描述了一般的場景)。線程可以通過Set方法使事件對象變為觸發狀態,這樣如果有一個線程正在等待這個對象觸發,那么相當於它將收到“事件通知”而返回。AutoReset的事件內核對象在被設置為觸發態后將自動回到非觸發態,ManualReset的事件對象不會自動重置為未觸發狀態。

.NET的封裝相應的有兩個版本,自動重置和手動重置,他們實際上是一樣的對象,只是行為稍有不同而已。在初始化事件對象的時候可以指定事件對象的初始化狀態:

static AutoResetEvent myResetEvent = new AutoResetEvent(false);//初始化為非觸發狀態

調用Set方法將事件對象置為觸發狀態:

event_1.Set();

調用Reset方法將事件對象置為非觸發狀態:

event_1.Reset();

調用WaitOne、WaitAny或WaitAll來使線程等待事件對象,它們的用法可以顧名思義。

下面對比一下.NET封裝的事件對象和windows原生的事件對象,關於windows原生的事件內核對象參見【Windows】線程漫談——線程同步之等待函數和事件內核對象

.NET Windows API 說明
AutoResetEvent CreateEvent(bManualReset=false)  
ManualResetEvent CreateEvent(bManualReset=true)  
.Set SetEvent  
.Reset ResetEvent  
AutoResetEvent PulseEvent .NET沒提供PulseEvent,對於事件對象而言,用AutoResetEvent代替
-- Named .NET下事件對象似乎無法命名,也就是說事件對象不能跨進程。但是Windows原生的事件對象是跟其他內核對象一樣是可以命名的,因此可以跨進程共享
EventWaitHandle.WaitOne WaitForSingleObject .NET通過在基類EventWaitHandle中定義Wait系列函數,封裝了等待函數
EventWaitHandle.WaitAll WaitForMultipleObjects
(bWaitAll=true)
 
EventWaitHandle.WaitAny WaitForMultipleObjects
(bWaitAll=false)
 

 

Mutex

.NET下單Mutex和Win32下單Mutex就是同一個東西,所以,完全可以從Win32的互斥量內核對象來理解。跟通常的內核對象一樣,互斥量具有觸發和未觸發兩種。當對象為觸發狀態的時候,等待他的線程將獲得其訪問權,並置為未觸發狀態;反之,對象為未觸發狀態時,等待他的線程將掛起。與Monitor和lock相同,Mutex也有記錄所屬線程ID,使用計數和遞歸計數,因此,同一個線程可以多次獲得同一個Mutex的訪問權限,但是要保證能夠有相同次數的釋放。

通過構造函數創建Mutex對象

private static Mutex mut = new Mutex();

除了不帶參數的構造函數,還有一些可選的參數用於創建Mutex對象:可以初始化創建的線程是否立刻擁有Mutex的訪問權限、可以為Mutex命名,命名的Mutex可以對其他進程可見,而不僅僅是本進程的線程。關於命名MSDN還有如下的說明:

在運行終端服務的服務器上,已命名的系統 mutex 可以具有兩級可見性。 如果名稱以前綴“Global\”開頭,則 mutex 在所有終端服務器會話中均為可見。 如果名稱以前綴“Local\”開頭,則 mutex 僅在創建它的終端服務器會話中可見。 在這種情況下,服務器上各個其他終端服務器會話中都可以擁有一個名稱相同的獨立 mutex。 如果創建已命名 mutex 時不指定前綴,則它將采用前綴“Local\”。 在終端服務器會話中,只是名稱前綴不同的兩個 mutex 是獨立的 mutex,這兩個 mutex 對於終端服務器會話中的所有進程均為可見。 即:前綴名稱“Global\”和“Local\”說明 mutex 名稱相對於終端服務器會話(而並非相對於進程)的范圍。

通過Mutex.Wait系列函數嘗試獲得對Mutex的訪問權限

mut.WaitOne();

通過Mutex.ReleaseMutex釋放Mutex

mut.ReleaseMutex();

在我之前的文章【Windows】線程漫談——線程同步之信號量和互斥量中詳細闡述了Win32下互斥量對象,下面對兩種API作一個比較

.NET Windows API 說明
Mutex CreateMutex  
Mutex OpenMutex  
.ReleaseMutex ReleaseMutex  
Mutex(bool,string) Named .NET下可以對Mutex對象命名
EventWaitHandle.WaitOne WaitForSingleObject .NET通過在基類EventWaitHandle中定義Wait系列函數,封裝了等待函數
EventWaitHandle.WaitAll WaitForMultipleObjects
(bWaitAll=true)
 
EventWaitHandle.WaitAny WaitForMultipleObjects
(bWaitAll=false)
 

勞動果實,轉載請注明出處:http://www.cnblogs.com/P_Chou/archive/2012/08/19/event-and-mutex-in-net-thread-sync.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM