为什么在Java的Object类中声明wait()和notify()?
为什么在Object
类中声明wait()
和notify()
方法,而不是Thread
类?
因为,你等待一个给定的对象(或者特定的监视器)来使用这个function。
我想你可能会误解这些方法是如何工作的。 它们不是简单地处于线程粒度级别,也就是说, 不是只调用wait()
,而是在notify()
的下一个调用中被唤醒。 相反,你总是在一个特定的对象上调用wait()
,并且只会被调用唤醒来notify
该对象 。
这很好,因为否则并发原语不会缩放; 这相当于拥有全局名称空间,因为在程序中的任何地方调用notify()
都可能会混淆任何并发代码,因为它们会唤醒在wait()
调用上阻塞的任何线程。 因此,你称他们为特定对象的原因; 它给出了wait-notify对的上下文,所以当你调用myBlockingObject.notify()
,你可以确定你只会唤醒在你的类中调用wait方法的线程。 一些可能正在等待另一个对象的Spring线程不会被这个调用唤醒,反之亦然。
编辑:或从另一个angular度来解决它 – 我期望从你的问题你以为你会得到一个处理等待的线程和调用notify()
该线程唤醒它。 没有这样做的原因是,你将不得不自己做很多家务。 要等待的线程必须在其他线程可以看到的地方发布对自身的引用; 这将不得不妥善同步执行一致性和可见性。 而当你想要唤醒一个线程时,你必须得到这个参考,唤醒它,然后把它从你阅读的地方移开。 涉及到更多的手动脚手架,与在睡眠线程中调用myObj.wait()
,然后在waker线程中调用myObj.wait()
相比,更有可能出错(尤其是在并发环境中)。
最简单明显的原因是任何对象(不只是一个线程)都可以作为线程的监视器。 在监视器上调用wait和notify。 正在运行的线程与显示器进行检查。 所以等待和通知方法是在对象而不是线程
因为一次只有一个线程可以拥有一个对象的监视器,而这个监视器是线程正在等待或通知的。 如果您阅读Object.notify()
和Object.wait()
的javadoc , Object.notify()
详细介绍它。
同步的机制涉及一个概念 – 监视一个对象。 当wait()被调用时,监视器被请求并且进一步执行被暂停,直到获取监视器或发生了InterruptedException。 notify()被调用时,显示器被释放。
假设wait()和notify()放在Thread类而不是Object类中, 在代码中的一个地方,调用currentThread.wait()
,然后访问一个对象anObject
。
//......... currentThread.wait(); anObject.setValue(1); //.........
当调用currentThread.wait()时,会请求currentThread
监视器,直到获取监视器或发生InterruptedException,才会执行进一步的执行。 现在处于等待状态时,如果另一个线程调用驻留在currentThread
的另一个对象anotherObject
的方法foo()
,即使被调用的方法foo()
不访问anObject
,它也会被卡住。 如果在anObject
调用第一个wait()方法而不是线程本身,则驻留在同一线程中的对象上的其他方法调用(不访问对象)不会卡住。
因此,在Object类(或其子类)上调用wait()和notify()方法会提供更高的并发性,这就是为什么这些方法在Object类中,而不在Thread类中。
在这里阅读等待和通知的解释。
然而,在应用程序中避免这些会更好,并使用更新的java.util.concurrent包。
我将以一种简单的方式说明:
要调用wait()或notify(),您需要拥有对象监视器 – 这意味着wait()或notify()需要存在于同步块中
synchronized(monitorObj){ monitorObj.wait() or even notify }
这就是这些方法出现在对象类中的原因
这是因为,这些方法是用于线程间通信的,而线程间通信是通过使用锁来实现的,而锁则是与对象相关联的,因此它们在对象类中。
在Java中的两个线程之间使用Wait和Notify方法进行通信。 所以Object类是正确的地方,使它们可用于Java中的每个对象。
另一个原因是锁是可用的每个对象的基础上。 线程需要锁,他们等待锁,他们不知道哪个线程持有锁,而只是知道锁被某个线程持有,他们应该等待锁,而不是知道同步块内的哪个线程,并要求他们释放锁
其他一些答案使用“监视”一词,但没有解释它的意思。
“监视器”的名字早在20世纪70年代就被创造出来了,它提到了一个拥有自己内在locking的对象,以及相关的等待/通知机制。 https://en.wikipedia.org/wiki/Monitor_%28synchronization%29
二十年后,桌面多处理器计算机出现了一个短暂的时刻,认为为他们devise软件的正确方法是创build面向对象的程序,其中每个对象都是监控。
事实certificate,这并不是一个有用的想法,但是那个短暂的时刻正好是Java编程语言发明的时候。