java中多線程協同工作是經常的事,眾所周知這種協同大多是通過wait()和notify()或者notifyAll()來實現的,然而在這個實現中有一點還是值得注意的。請看下面的樣本:
thread1:synchronized(sharedMonitor){ someCondition = false; sharedMonitor.notify();}thread2:while(someCondition){//point 1synchronized(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訊號。