繁体   English   中英

在同步块中使用wait()方法时,JVM是否在等待notify()时释放监视器?

[英]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调用之前notifyonPerformed方法。

thread1将正确看到此标志的值,因为thread2thread1获取同一监视器之前释放了监视器,并且这建立了Java内存模型规范中所述的事前发生关系。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM