[英]When using wait() method in a synchronized block does JVM release the monitor while waiting for notify()?
我有一個線程啟動另一個線程,該線程執行的操作將導致事件在運行后觸發。 我需要在第一個線程中捕獲該事件(通過事件偵聽器),然后繼續其余的工作。 我的問題是,當第一個線程正在等待事件偵聽器調用notify()
時,它將釋放監視器嗎? 如果沒有,我該如何設計該算法? 我是否正確地使用了wait()
和notify()
方法並獲得了正確的鎖(線程1)?
代碼如下所示:
public class Thread1 {
public void run() {
Thread thread1 = Thread.currentThread();
EventListener listener = new EventListener(thread1);
Performer performer = new Performer();
performer.addOnPerformedListener(listener);
synchronized(thread1) {
performer.run(); // Launches thread 2
thread1.wait();
}
...
}
public class EventListener implements Performer.OnPerformedListener {
private Thread thread;
public EventListener(Thread thread) {
this.thread = thread;
}
@Override
public void onPerformed() {
synchronized (thread) {
thread.notify();
}
}
}
}
這很近。 但是,很難(在執行者中)知道沒有其余代碼有多接近。
首先,我建議不要在“ performer.run()
”調用上保持線程的鎖-如果可行的話。 盡可能使關鍵部分(保持鎖的代碼執行)盡可能小是“最佳實踐”。
其次,我建議使用在執行者中設置的條件標志(如果我正確理解了代碼),並在調用wait()之前在關鍵部分內執行檢查-以便錯過的通知不會導致錯過的條件。
這是偽代碼:
THREAD1
* Initialize THREAD2
* Start THREAD2
* synchronized ( THREAD2 ) { while ( THREAD2.conditionNotMet() ) { THREAD2.wait(); } }
THREAD2
* Initialize "condition not met"
* Run
* On condition met, set "condition met", then synchronized ( THREAD2 ) { THREAD2.notifyAll(); }
此外,如果該條件可能多次出現,並且等待該條件的代碼僅想在新出現的情況下繼續,請嘗試使用序列號,而不是僅“滿足條件”(例如, if ( myLastOccurrenceNumber < THREAD2.getLastOccurenceNumber ) { MET-CONDITION ) } else { WAIT }
)。
您正在做什么的基本想法是正確的。 如Object#wait()
方法的Javadoc所述,它在Object#wait()
時釋放您使用synchronized
語句獲取的監視器:
當前線程必須擁有該對象的監視器。 線程釋放此監視器的所有權,並等待直到另一個線程通知等待在此對象的監視器上喚醒的線程
但是,有一個原因不能保證在您實施時在每種情況下都能正常工作,原因是wait
調用也可以通過“中斷和虛假喚醒”來喚醒。 (它可以在您當前已實施的99%的情況下正常工作,這使其變得更加棘手,因為這會誤以為它會一直工作)
如Javadoc所述:
與一個參數版本中一樣,可能會產生中斷和虛假喚醒,並且應始終在循環中使用此方法:
synchronized (obj) { while (<condition does not hold>) obj.wait(); ... // Perform action appropriate to condition }
所以,你還需要什么來表示“執行”的情況做-the最簡單的方法是創建一個boolean
名為場performed
,你設置為true
調用之前notify
在onPerformed
方法。
thread1
將正確看到此標志的值,因為thread2
在thread1
獲取同一監視器之前釋放了監視器,並且這建立了Java內存模型規范中所述的事前發生關系。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.