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信號。