0

如果一個線程試圖獲取一個鎖並取得鎖,它應該進入休眠狀態並保持睡着狀態,直到釋放鎖。如果一個線程釋放一個鎖(並且它由創建它的線程取得),它應該喚醒線程。實現鎖定和阻塞線程

我的問題是,如果我們喚醒鎖地址上的所有線程與鎖地址上的單線程(鎖釋放後)是否有區別?如果我們要喚醒一個單獨的線程,哪一個線程有意義醒來,第一個線程應該鎖定在鎖定地址上?

我可以看到喚醒一個線程的一些優勢,因爲如果我們全部喚醒,n-1可能會回到睡眠狀態。但我不知道喚醒單線程是否有缺點。

+2

如果它是一個鎖(互斥,臨界區),有什麼能喚醒一個以上的線程在等待它的意義呢?當它似乎是唯一可能發生的事情時,爲什麼「他們*可能會*重新入睡」? –

回答

2

我相信你混淆窗戶鎖(互斥,臨界區)與.net顯示器(在C#中可以使用關鍵字鎖定爲語法糖進入/退出塊。)

的Windows互斥和關鍵部分只能進入和退出,即只有一個隊列與它們相關聯。隊列中的所有線程都會等待鎖被釋放,當發生這種情況時,隊列上的下一個線程將控制鎖並開始運行。所有這些都自動發生。當前持有鎖的線程沒有任何部分,它不能選擇喚醒等待鎖釋放的其他線程中的一個或多個線程。

.Net's Monitor有兩個隊列:一個就緒隊列和一個等待隊列。

就緒隊列的行爲與Win32 Mutex或Critical Section隊列完全相同,並使用Enter/Leave方法進行控制。

等待隊列是使用Wait/Pulse/PulseAll方法控制的單獨隊列。這些方法只能由持有Monitor的線程調用。當一個線程調用等待它釋放監視器並進入等待隊列。然後不同的線程可以調用Pulse移動一個線程或Pulse All將所有線程從等待移動到就緒隊列(請記住調用Pulse/PulseAll的線程持有Monitor)。

從計算機科學的角度來看監控器是需要同步線程(信號量,事件,互斥體,障礙等可以用監視器實現的)的單個原語,從實際的角度來看,監視器作爲互斥體以及需要由兩個線程鎖定步驟。但大多數情況下,使用事件時代碼更具可讀性。

延伸閱讀:

Wikipedia page about Monitors for the historic/computer science aspect

MSDN Monitor class

+0

由於OP在任何地方都沒有提到.Net,所以我想知道爲什麼你從一開始就談論.Net監視器。如果OP感到困惑的是,監視器是.Net特有的東西,但這是一個通用的概念,否則你會很好地解釋它。 –

+0

@Pavel你可能是對的。在我看來,就像給出這個問題的最可能的錯誤。 .Net監視器是使用「鎖定」關鍵字唯一受歡迎的同步原語,可以喚醒其他線程。我可以編輯答案以清楚地說明Monitor是一個通用的概念,並不特別與.Net聯繫在一起。 –