簡體   English   中英

為什么 Monitor.Wait() 和 Monitor.Pulse() 需要鎖?

[英]Why do Monitor.Wait() and Monitor.Pulse() require a lock?

為什么調用這些需要鎖?

https://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystified

這篇文章暗示了一些關於條件變量等的內容,但我不明白為什么我希望總是使用它。

我的意思是,如果有必要在調用 Wait() 或 Pulse() 之前獲取鎖,為什么不在內部實現它作為它們的一部分呢? 或者為什么不讓 Wait 和 Pulse 原子化,讓開發人員隨心所欲地使用這些功能?

這就是我所說的“需要鎖”的意思:

Monitor.Pulse(_lock)將不起作用,但lock (_lock) { Monitor.Pulse(_lock); } lock (_lock) { Monitor.Pulse(_lock); }一樣。

因為 monitor.wait 的目的是釋放對象上的鎖。 這些是靜態方法,因此除了通過參數之外,沒有指示應該釋放哪個對象的狀態,因此必須傳入

此外,這里的目的是允許將鎖用於某種目的,然后在 Monitor.Wait 中釋放。 將它鎖定然后由監視器解鎖不會實現任何目標

不持有鎖,你肯定會遇到競爭條件。 假設線程 A 將調用Wait並且線程 B 將調用Pulse 重要的是線程 A 在線程 B 發送脈沖之前已經在等待。 如果線程 B線程 A 開始等待之前發送脈沖,則脈沖什么也不做,線程 A 將無限期地等待。 我們怎么知道線程 A 正在等待? 好吧,它可以在開始等待之前發送一條消息(例如設置一個標志或將一個項目放入隊列中),但是如果發送消息然后另一個線程在它開始等待之前被調度怎么辦? 僅僅因為它已經發送了它打算開始等待的消息,並不意味着它實際上已經開始等待了! 知道線程 A 確實已經進入等待的唯一方法是讓 A 在發送消息時持有鎖,在它開始等待時自動釋放鎖,讓 B 獲取鎖,然后觀察 A 的消息。

現在,好吧,也許你可以設計一種情況,B 確定 A 已經開始等待,釋放鎖,做一些其他的事情,然后想要在釋放鎖后發送一個脈沖來喚醒 A,但你會遇到類似的情況當您想再次使用監視器時,或者您想讓更多線程等待或脈沖時出現問題。 或者,也許您說您不在乎錯過脈沖,您只會繼續發送更多……但隨后您將轉向輪詢並浪費PulseWait的好處。

簡而言之,您需要在等待之前保持鎖定,因為這是可靠地傳達存在等待脈沖的實體的唯一方法。 您需要在脈沖之前保持鎖定,因為這是可靠地發現存在准備接收脈沖的實體的唯一方法。 如果沒有這些行為,Monitor 就不是在其上構建更高級同步機制的有用原語。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM