2011-01-21 48 views
1

之前爲什麼必須獲取監視器如果一個線程在它當前沒有擁有的鎖定對象上調用Monitor.Wait(lockObj),則會拋出一個SyncronizationLockException在調用Monitor.Wait()

我不明白這一點嗎?如果線程擁有該鎖,並因此可以成功呼叫Monitor.Wait(),那麼它就會立即釋放鎖。爲什麼線程不能等待它目前不擁有的鎖?


更新

我已經決定要詳細說明一下添加到我的問題。

從我的理解等待只是將當前線程放在顯示器等待隊列並釋放鎖。稍後,脈衝或脈衝都會將等待隊列上的一個或所有線程移至就緒隊列。只要監視器被釋放,就緒隊列中的下一個(如果有的話)線程就會被鎖定。

那麼,爲什麼不能等待簡單地將線程添加到等待隊列?爲什麼它需要獲得鎖來做到這一點?這是否有物理上的原因,或者微軟設計這個類迫使你以正確的方式使用它?

現在我想到了它,我猜想把一些東西放在顯示器的等待隊列中,或者將某些東西移動到就緒隊列中真的是在操縱顯示器。這是有道理的,你需要自己的監視器來做到這一點。這是想想它的正確方法嗎?

因爲我的大腦多線程很難!

回答

1

Monitor.Wait的要點是讓其他線程有機會抓住你的鎖。

如果你一開始沒有鎖,那就沒有意義了;其他線程可以搶鎖。
(除非是一些其他線程已經擁有的鎖,在這種情況下調用Wait會搞糟線程)

0

調用Monitor.Wait沒有鎖,但這在大多數情況下,引入非確定性的bug。如果你在獲取一個鎖之後調用Monitor.Wait,並且在獲取一個鎖和呼叫Monitor.Wait之間不設置任何共享變量。

特別是 - 如果您沒有自己的鎖,那麼在輸入Monitor.Wait之前,您永遠無法確定隨附的Monitor.Pulse尚未執行。考慮一下操作系統在Monitor.Wait調用之前掛起線程A並在執行一些計算後恢復正在執行Monitor.Pulse的線程B的情況。所有共享變量說服線程B,A正在等待,但這根本不是真的。此時線程A不能停止執行Monitor.Wait

另外 - 你可能會對Semaphores http://en.wikipedia.org/wiki/Semaphore_(programming的想法感興趣。您可以等待併發出信號,而無需獲取它們。這是因爲他們擁有一個國家。所以如果你先發信號然後等待不會鎖定。

1

Monitor.Wait用於釋放鎖定,然後以原子方式重新獲取該鎖定。 BCL中沒有其他同步機制聲稱有名氣。顯然Wait如果還不存在,就不能重新獲取鎖定。這就是拋出異常的原因。

Wait重新獲得現有鎖的事實是一個非常強大的機制。正是這種行爲的基本獨特性使其能夠用於構建BCL中的所有其他同步機制。