为啥方法 wait() 在没有 notify() 的情况下工作?

Posted

技术标签:

【中文标题】为啥方法 wait() 在没有 notify() 的情况下工作?【英文标题】:Why method wait() works without notify()?为什么方法 wait() 在没有 notify() 的情况下工作? 【发布时间】:2014-03-28 16:55:26 【问题描述】:

非常感谢!

我在同步 2 个线程时遇到了问题:主线程和从 StepRunner.java 调用的线程。我只需要在下一次迭代开始之前显示迭代结果。

我想要什么:

Please enter step number [1, 2, 3 or 4] or 5 for exit: 2
Please enter natural value for factorial computing: 2
2! = 2
Please enter step number [1, 2, 3 or 4] or 5 for exit:

我不想要的:

Please enter step number [1, 2, 3 or 4] or 5 for exit: 2
Please enter natural value for factorial computing: 2
Please enter step number [1, 2, 3 or 4] or 5 for exit: 2! = 2

为此,我在 StepRunner.java 中有同步块:

public void run() 
        thread.start();
        synchronized (thread) 
            try 
                while (thread.isAlive())  /**Loop is an Oracle's recommendation*/
                    thread.wait();
                
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
    

但是为什么方法 wait() 在我的代码的任何地方没有方法 notify() 也能正常工作?

【问题讨论】:

您是否检查过循环是否已执行?这只是一个猜测,但也许线程拥有自己的监视器(或者调度程序拥有),因此同步块仅在线程完成后执行并且不再活跃。 当线程死亡时它会通知自己。 【参考方案1】:

Thread's javadoc 声明Thread.notifyAll() 在线程完成时在内部被调用:

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

如您所见,不建议使用此功能,您的代码可以改写如下:

thread.start();
try 
    thread.join();    
 catch (InterruptedException e) 
    e.printStackTrace();

鉴于此语句仅出现在 Java 7 javadoc 中,建议不要使用此功能,看起来此行为曾经是 Thread 类的实现细节,但人们开始依赖它,所以该语言作者必须记录它。

【讨论】:

以上是关于为啥方法 wait() 在没有 notify() 的情况下工作?的主要内容,如果未能解决你的问题,请参考以下文章

java同步中,为啥要wait,又notify谁?

java的notify方法为啥也要同步

为啥在 Java 的 Object 类中声明 wait() 和 notify()?

Java 线程中调用wait为啥一定要在同步代码块中?

如何在不是线程的对象上调用 wait() 和 notify() 方法?

(二)线程状态、wait/notify