等待方法在不调用通知的情况下唤醒(非虚假唤醒)



在下面的语句中,即使没有调用通知,也会执行 wait() 方法,但语句below wait()仅在线程完成执行后执行laurel

我尝试使用其他对象锁定 hardy 块的同步,这次等待方法仍然永远等待,有人可以解释为什么执行 wait() 后的语句吗?

package delagation;
public class Solution extends Thread {
    static Thread laurel, hardy;
    public static void main(String[] args) throws InterruptedException {
        laurel = new Thread() {
            public void run() {
                System.out.println("A");
                try {
                    hardy.sleep(1000);
                } catch (Exception e) {
                    System.out.println("B");
                }
                System.out.println("C");
            }
        };
        hardy = new Thread() {
            public void run() {
                System.out.println("D");
                try {
                    synchronized(laurel) {
                        laurel.wait();
                        //wait method is called here, 
                        //There is not notify in this class, 
                        //but the statement below are executing
                        System.out.println(Thread.currentThread().getName());
                    }
                } catch (Exception e) {
                    System.out.println("E");
                }
                System.out.println("F");
            }
        };
        laurel.setName("laurel");
        hardy.setName("hardy");
        laurel.start();
        hardy.start();
    }
}

你不需要假设一个虚假的唤醒来解释这里发生了什么。当 laurel 终止时,它会向正在等待它的线程发送通知。(这就是 Thread.join 的工作方式。

请参阅 Thread#join 的 api 文档:

此实现使用 this.wait 调用的循环,条件为 this.isAlive。当线程终止时,将调用 this.notifyAll 方法。建议应用程序不要在 Thread 实例上使用等待、通知或通知全部。

此外,始终使用条件在循环中等待;请参阅 Oracle 并发教程,尤其是受保护块页面。(从描述中,您可以看到 join 等待在一个循环中,其中测试的条件在连接到的线程上是 isAlive,所以这是一个很好的例子。您可以在 Thread 类的 jdk 源代码中找到联接方法。

最新更新