[英]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.