java線程協作---錯失的信號(thinking in java 筆記)

java中多線程協同工作是經常的事,衆所周知這種協同大多是通過wait()和notify()或者notifyAll()來實現的,然而在這個實現中有一點還是值得注意的。請看下面的示例:

thread1:
synchronized(sharedMonitor)
{
      someCondition = false;
      sharedMonitor.notify();
}

thread2:
while(someCondition)
{
	//point 1
	synchronized(sharedMonitor)
	{
		sharedMonitor.wait();
	}
}

如果thread2先執行,執行到point 1的時候線程調度器將線程切換到thread1,thread1執行其設置並執行notify(),而此時線程切回thread2繼續執行完,這個時候,thread2就會進入無限的忙等狀態,因爲在它執行wait()之前thread1已經執行完了notify(),因此thread2就錯失這個信號,這樣就會產生死鎖。這個問題的解決方案是防止在在someCondition變量上產生競爭條件,如果將thread2修改爲下面這樣就可以達到這個目的了:

synchronized(sharedMonitor)
{
	while(someCondition)
	{
	    sharedMonitor.wait();
	}
}

這個時候如果thread1先執行,無論在何處線程發生切換,thread2都不可能執行,因爲thread1沒有釋放sharedMonitor對象上的鎖,thread2只能等待thread1執行完並釋放鎖之後纔可以執行,而當thread1執行完後someCondition的值被修改這一事件就會被thread2所捕獲,這樣在someCondition=false的條件下thread2不會進入wait()狀態,相反加入thread2先執行,同樣不論線程切換在何處發生,thread1都必須等到thread2中的synchronized代碼塊全部執行完纔可以執行,因爲thread2已經獲取了sharedMonitor對象的鎖且必須等到wait()執行完畢之後纔會釋放鎖,所以這個時候thread2就不會錯失thread1的notify信號。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章