有一個主線程有一個while循環,在此期間,當他檢查一些條件時,如果滿足所有條件,他將啓動另一個線程進入wait()狀態。等待並通知協調
並行運行的其他線程在工作完成時通知主線程。
當「子線程」在之前通知主線程時,主線程進入等待狀態=死鎖存在問題。
避免它的最佳做法是什麼?
有一個主線程有一個while循環,在此期間,當他檢查一些條件時,如果滿足所有條件,他將啓動另一個線程進入wait()狀態。等待並通知協調
並行運行的其他線程在工作完成時通知主線程。
當「子線程」在之前通知主線程時,主線程進入等待狀態=死鎖存在問題。
避免它的最佳做法是什麼?
只要確保主線程不會等待已發生的事情。 (爲什麼有人會那樣做呢?這沒有任何意義。)
我寧願使用明確的Locks。請參閱Java Concurrent Api。
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html
使用旗語的通知。
就是這樣,真的。信號量有一個計數,並可以記錄通知,直到主線程開始等待。
簡單的答案是使用Java 5中的併發包。CountDownLatch在這裏看起來很合適。
如果您僅限於Java 5之前的環境,則必須創建一個使用相同算法的自定義實現。創建所有子線程後,主線程將調用signalReady。子線程在完成工作後會調用signalComplete。
一個簡單的實現是將一個名爲Latch的Object帶有兩個兩個成員字段。
以下實施將適用於一位家長和一位子女。對於額外的孩子,每個孩子在完成時都可以給自己的閂鎖發出信號。仍然會有這種情況會導致競賽狀況。在信號之間添加旋轉鎖定或可能是睡眠會降低競爭條件的可能性。 它不會消除它
class Latch{
Object readyLock;
Object completeLock;
public void signalComplete(){
synchronized(readyLock){
readyLock.wait()
}
//spin lock as a precaution
synchronized(completeLock){
completeLock.notify()
}
}
public void signalReady(){
synchronized(readyLock){
readyLock.notify()
}
synchronized(completeLock){
completeLock.wait()
}
}
}
希望這有助於!
這段代碼被破壞嚴重,並造成OP詢問的問題!即使沒有什麼需要等待,signalReady函數也會等待。 'signalComplete'函數完成同樣的事情。 – 2012-07-18 07:18:19
這是一個非常普遍的做法幾乎總是把wait()
方法在while
循環,其「迭代條件」是檢查是否已經發生特定事件時,發生其中的其他線程會被稱爲notify()
方法。
例如:
while(!event_occurrence) {
...
wait();
...
}
其中event_occurrence
是其另一個線程會叫notify()
法事件。
我不認爲這將有助於:如果有2個子線程。第一個子線程完成=> event_occurrence = true,主線程進入while循環。此時(執行wait()之前)子線程2完成。那麼主線程再次執行wait()=>死鎖 – markiz 2012-07-18 07:32:12
@markiz:子線程2無法完成,除非此線程處於「等待」狀態,因爲此線程持有鎖。 (它調用'wait'來釋放鎖以及等待事件。) – 2012-07-18 08:31:50
@David Schwartz,鎖定主線程。子線程喚醒主線程。主線程產生子線程並等待它們中的任何一個完成。然後他做了一些邏輯並再次入睡。 – markiz 2012-07-18 09:52:44
+1:wait()的javadoc明確地解釋了應始終有一個循環檢查進入/退出等待狀態的條件。 – 2012-07-18 05:49:50