monitor mutex lock in .net

NET Framework 開發人員指南 
同步基元概述 

 

.NET Framework 提供了一系列同步基元來控制線程交互並避免爭用條件。這可大致分爲三個類別:鎖定、通知和聯鎖操作。

上述類別的定義並非是絕對的:有些同步機制具有多個類別的特徵;一次釋放一個線程的事件的功能類似於鎖定;任何鎖定的釋放都可看作一個信號;而聯鎖操作可用於構造鎖定。但是,這些類別仍然是有用的。

記住線程同步是協作這一點非常重要。只要有一個線程避開同步機制直接訪問受保護的資源,該同步機制就不是有效的。

鎖定

鎖向一個線程一次提供一個資源的控制功能,或者向指定數目的線程提供此功能。請求正在使用中的獨佔鎖的線程會被阻止,直到該鎖變爲可用爲止。

獨佔鎖

鎖定的最簡單的形式是 C# 的 lock 語句(在 Visual Basic 中爲 SyncLock),該語句可控制對代碼塊的訪問。這種塊通常稱爲臨界區。lock 語句使通過使用 Monitor 類的 EnterExit 方法實現的,它使用 try…catch…finally 確保該鎖被釋放。

通常情況下,使用 lock 語句保護小代碼塊並且不跨越多個方法是使用 Monitor 類的最佳方法。Monitor 類功能強大,但是容易形成孤立鎖和死鎖。

Monitor 類

Monitor 類提供了附加功能,可結合 lock 語句使用:

  • TryEnter 方法允許當前被阻止,正在等待資源的線程在指定時間間隔之後放棄。它返回一個指示成功或失敗的布爾值,可用於檢測和避免潛在的死鎖。

  • Wait 方法由臨界區中的線程調用。它放棄對資源的控制並阻止,直到該資源重新可用爲止。

  • PulsePulseAll 方法允許要釋放鎖或調用 Wait 的線程將一個或多個線程放入就緒隊列,以使它們能夠獲取鎖。

Wait 方法重載的超時允許等待線程進入就緒隊列。

如果用於鎖的對象派生自 MarshalByRefObject,則 Monitor 類可在多個應用程序域中提供鎖定。

Monitor 具有線程關聯。也就是說,進入監視器的線程必須通過調用 ExitWait 才能退出。

Monitor 類不可實例化。其方法是靜態(在 Visual Basic 中爲 Shared)方法,用於可實例化的鎖對象。

有關概念性概述,請參見監視器

Mutex 類

線程通過調用其 WaitOne 方法的重載請求 Mutex。提供了具有超時的重載,以便允許線程放棄等待。與 Monitor 類不同,mutex 可以是局部的,也可以是全局的。全局 mutex(也稱爲命名的 mutex)在整個操作系統中可見,可用於在多個應用程序域或進程中同步線程。局部 mutex 派生自 MarshalByRefObject,可以跨應用程序域邊界使用。

此外,Mutex 派生自 WaitHandle,這意味着它可用於 WaitHandle 提供的通知機制,如 WaitAllWaitAnySignalAndWait 方法。

Monitor 一樣,Mutex 具有線程關聯。與 Monitor 不同,Mutex 是可實例化的對象。

有關概念性概述,請參見 Mutex

其他鎖

鎖定不必是獨佔的。允許有限數目的線程併發訪問某個資源通常十分有用。信號量和讀寫器鎖旨在控制此類池資源訪問。

ReaderWriterLock 類

ReaderWriterLock 類用於更改數據的線程(編寫器)必須獨佔訪問某個資源的情形。如果編寫器不是活動的,則任何數量的讀取器均可通過調用 AcquireReaderLock 方法訪問該資源。一旦有線程調用 AcquireWriterLock 方法,後續讀取器請求則會阻止,直到所有現有讀取器均釋放了該鎖,並且有一個編寫器獲取並釋放了該鎖爲止。

ReaderWriterLock 具有線程關聯。

有關概念性概述,請參見讀取器/編寫器鎖

Semaphore 類

Semaphore 類允許指定數目的線程訪問某個資源。請求該資源的其他線程會一直阻止,直到某個線程釋放信號量爲止。

Mutex 類一樣,Semaphore 派生自 WaitHandleSemaphore 也與 Mutex 一樣,可以是局部的,也可以是全局的。它可以跨應用程序域邊界使用。

MonitorMutexReaderWriterLock 不一樣,Semaphore 不具有線程關聯。這意味着它可以用於一個線程獲取信號量而另一個線程釋放該信號量的情形。

有關概念性概述,請參見信號量

通知

等待另一個線程的信號的最簡單方法是調用 Join 方法,該方法會一直阻止,直到另一個線程完成爲止。Join 有兩個重載方法,這兩個方法允許阻止的線程在等待指定時間間隔之後跳出等待。

等待句柄提供了更爲豐富的等待和通知功能。

等待句柄

等待句柄派生自 WaitHandle 類,後者又派生自 MarshalByRefObject。因此,等待句柄可用於跨應用程序域邊界同步線程的活動。

通過調用實例方法 WaitOne 或者靜態方法 WaitAllWaitAnySignalAndWait 中的一個方法,線程可由等待句柄阻止。它們的釋放方式取決於調用的方法以及等待句柄的種類。

有關概念性概述,請參見等待句柄

事件等待句柄

事件等待句柄包括 EventWaitHandle 類及其派生類 AutoResetEventManualResetEvent。當通過調用 Set 方法或使用 SignalAndWait 方法通知事件等待句柄時,線程會從事件等待句柄釋放。

事件等待句柄要麼自動重置自身(類似於每次得到通知時只允許一個線程通過的旋轉門),要麼必須手動重置(類似於在通知前一直關閉,有人將其關閉前則一直打開的大門)。顧名思義,AutoResetEventManualResetEvent 分別表示前者和後者。

EventWaitHandle 可表示這兩種類型的事件,並且既可以是局部的也可以是全局的。派生類 AutoResetEventManualResetEvent 始終是局部的。

事件等待句柄不具有線程關聯。任何線程都可以通知事件等待句柄。

有關概念性概述,請參見 EventWaitHandle、AutoResetEvent 和 ManualResetEvent

Mutex 和 Semaphore 類

因爲 MutexSemaphore 類派生自 WaitHandle,所以它們可用於 WaitHandle 的靜態方法。例如,線程可以使用 WaitAll 方法等待,直到滿足以下三個條件爲止:EventWaitHandle 接收到通知,Mutex 已釋放,Semaphore 已釋放。類似地,線程可以使用 WaitAny 方法等待,直到滿足上述所有條件爲止。

對於 MutexSemaphore,接收到通知即意味着被釋放。如果上述兩個類型之一用作 SignalAndWait 方法的第一個參數,該類型即被釋放。對於具有線程關聯的 Mutex,如果進行調用的線程不具有該 mutex,則會引發異常。如前所述,信號量不具有線程關聯。

聯鎖操作

聯鎖操作是由 Interlocked 類的靜態方法對某個內存位置執行的簡單原子操作。這些原子操作包括添加、遞增和遞減、交換、依賴於比較的條件交換,以及 32 位平臺上的 64 位值的讀取操作。

Note注意

原子性的保證僅限於單個操作;如果必須將多個操作作爲一個單元執行,則必須使用更粗粒度的同步機制。

儘管這些操作中沒有一個是鎖或信號,但它們可用於構造鎖和信號。因爲它們是 Windows 操作系統固有的,因此聯鎖操作的執行速度非常快。

聯鎖操作可用於可變內存保證,以編寫展示功能強大的非阻止併發的應用程序,但是,它們需要複雜的低級別編程,因此大多數情況下簡單鎖是更好的選擇。

有關概念性概述,請參見互鎖操作

請參見

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章