55

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

4

9 回答 9

43

因为,您等待给定的对象(或具体来说,它的监视器)来使用此功能。

我认为您可能对这些方法的工作方式有误。它们不只是处于线程粒度级别,即它不仅仅是调用wait()并被下一次调用唤醒的情况notify()。相反,您总是调用wait()一个特定的对象,并且只会被调用notify 该对象唤醒。

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

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

于 2009-11-20T10:12:10.720 回答
11

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

于 2009-11-20T10:13:15.183 回答
8

因为一次只有一个线程可以拥有一个对象的监视器,而这个监视器是线程正在等待或通知的。如果您阅读了javadocObject.notify()Object.wait()对其进行了详细描述。

于 2009-11-20T10:11:56.357 回答
1

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

假设 wait() 和 notify() 被放置在 Thread 类而不是 Object 类中。在代码中的某一时刻,currentThread.wait()调用了一个对象,然后anObject访问了一个对象。

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

当 currentThread.wait() 被调用时,monitor ofcurrentThread被请求并且不会进一步执行直到监视器被获取或者 InterruptedException 发生。现在在等待状态下,如果从另一个线程调用另一个对象的方法,foo()即使被调用的方法没有访问,它也会被卡住。如果调用第一个 wait() 方法,而不是线程本身,则对驻留在同一线程中的对象的其他方法调用(不访问)不会卡住。anotherObjectcurrentThreadfoo()anObjectanObjectanObject

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

于 2009-11-20T12:06:27.117 回答
1

其他一些答案使用“监视器”一词,但没有一个解释它的含义。

“监视器”这个名字早在 1970 年代就被创造出来了,它指的是一个拥有自己的内在锁和相关的等待/通知机制的对象。https://en.wikipedia.org/wiki/Monitor_%28synchronization%29

20 年后,有一个短暂的时刻,台式机、多处理器计算机是新的,流行的想法是为它们设计软件的正确方法是创建面向对象的程序,其中每个对象都是监视器。

事实证明这不是一个有用的想法,但那个短暂的时刻恰好是 Java 编程语言被发明的时候。

于 2015-12-15T15:26:09.933 回答
0

阅读此处了解等待和通知的说明。

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

于 2009-11-20T10:16:43.600 回答
0

我会用一种简单的方式说:

要调用 wait() 或 notify() 您需要拥有对象监视器 - 这意味着 wait() 或 notify() 需要存在于同步块中

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

这就是这些方法存在于对象类中的原因

于 2014-01-26T06:29:32.997 回答
0

这是因为,这些方法是用于线程间通信的,线程间通信是通过使用锁发生的,但锁是与对象相关联的。因此它在对象类中。

于 2014-04-25T16:03:51.247 回答
0

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

另一个原因是每个对象都可以使用锁。线程需要锁,他们等待锁,他们不知道哪些线程持有锁,他们只知道锁被某个线程持有,他们应该等待锁,而不是知道哪个线程在同步块内并要求他们释放锁

于 2015-08-17T06:33:05.737 回答