为什么在Java的Object类中声明了wait()和notify()?

时间:2009-11-20 10:01:41

标签: java multithreading wait notify

为什么在wait()类中声明了notify()Object方法,而不是Thread类?

9 个答案:

答案 0 :(得分:41)

因为,您在给定的Object(或特别是其监视器)上等待使用此功能。

我认为你可能会误解这些方法是如何工作的。它们不仅仅处于线程粒度级别,即只是调用wait()并在下次调用notify()时被唤醒的情况。相反,您始终在特定对象上调用wait(),并且只会通过调用该对象上的notify 来唤醒

这很好,因为否则并发原语就不会扩展;它等同于拥有全局命名空间,因为在程序中任何地方对notify()的任何调用都有可能弄乱任何并发代码,因为它们会唤醒任何阻塞{}的线程{1}}致电。因此你在特定对象上调用它们的原因;它为wait-notify对提供了一个上下文,所以当你在私有对象上调用wait()时,你可以确定你只会唤醒在你的类中调用wait方法的线程。可能正在等待另一个对象的一些Spring线程不会被此调用唤醒,反之亦然。

编辑:或者从另一个角度解决它 - 我希望你的问题,你认为你会得到等待线程的句柄,并在线程上调用myBlockingObject.notify()来唤醒它。它没有这样做的原因是你必须自己做很多家务。要等待的线程必须在其他线程可以看到的地方发布对自己的引用;这必须正确同步以强制一致性和可见性。当你想要唤醒一个线程时,你必须抓住这个引用,唤醒它,并从你读取它的任何地方删除它。与仅在睡眠线程中调用notify()然后在waker线程中调用myObj.wait()相比,涉及更多的手动脚手架,并且更多的机会出错(特别是在并发环境中)。

答案 1 :(得分:10)

最简单明了的原因是任何对象(不仅仅是一个线程) 可以是线程的监视器。等待和通知被调用 监控。正在运行的线程检查监视器。所以wait和notify方法是在Object而不是Thread

答案 2 :(得分:8)

因为一次只有一个线程可以拥有一个对象的监视器,而这个监视器就是线程正在等待或通知的内容。如果您阅读了Object.notify()的{​​{3}}和Object.wait(),请详细说明。

答案 3 :(得分:1)

其他一些答案使用“监视器”一词,但没有一个解释它意味着什么。

“监视器”这个名字是在20世纪70年代创造的,它引用了一个具有自己的内部锁定和相关的等待/通知机制的对象。 https://en.wikipedia.org/wiki/Monitor_%28synchronization%29

二十年后,桌面多处理器计算机出现了新的短暂时刻,认为为他们设计软件的正确方法是创建面向对象的程序,这是时尚的。 em>每个对象都是一个监视器。

原来并不是一个如此有用的想法,但那个短暂的时刻恰好恰好是Java编程语言的发明。

答案 4 :(得分:1)

同步机制涉及一个概念 - 监视对象。调用wait()时,将请求监视器并暂停执行,直到获取监视器或发生InterruptedException。调用notify()时,监视器将被释放。

如果将wait()和notify()放在Thread类而不是Object类中,那么我们来看一个场景。在代码中的某一点,调用currentThread.wait(),然后访问对象anObject

//.........
currentThread.wait();
anObject.setValue(1);
//.........

当调用currentThread.wait()时,请求监视currentThread,并且在获取监视器或发生InterruptedException之前不再执行。现在处于等待状态时,如果从另一个线程调用驻留在foo()中的另一个对象anotherObject的方法currentThread,即使被调用的方法foo()不存在,它也会被卡住访问anObject。如果在anObject上调用第一个wait()方法,而不是线程本身,则驻留在同一线程中的对象的其他方法调用(不访问anObject)不会卡住。

因此,在Object类(或其子类)上调用wait()和notify()方法可以提供更高的并发性,这就是为什么这些方法在Object类中,而不是在Thread类中。

答案 5 :(得分:0)

Wait和Notify方法用于Java中两个线程之间的通信。所以Object类是正确的位置,使它们可用于Java中的每个对象。

另一个原因是锁定是基于每个对象提供的。线程需要锁定并等待锁定,他们不知道哪些线程持有锁定而不知道锁定是由某个线程保持的,他们应该等待锁定而不是知道哪个线程在同步块内并询问它们释放锁定

答案 6 :(得分:0)

阅读here以获取有关等待和通知的说明。

最好在您的应用程序中避免这些,并使用较新的java.util.concurrent包。

答案 7 :(得分:0)

我会以简单的方式说出来:

要调用wait()或notify(),您需要拥有对象监视器 - 这意味着wait()或notify()需要出现在synchronized块中

synchronized(monitorObj){
monitorObj.wait()  or even notify
}

这就是对象类

中存在这些方法的原因

答案 8 :(得分:0)

这是因为,这些方法用于线程间通信,并且通过使用锁来进行interthread通信,但是锁与对象相关联。因此它在对象类中。