简体   繁体   English

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

[英]Why are wait() and notify() declared in Java's Object class?

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

Because, you wait on a given Object (or specifically, its monitor) to use this functionality. 因为,您在给定的Object(或特别是其监视器)上等待使用此功能。

I think you may be mistaken on how these methods work. 我想你可能会误解这些方法是如何工作的。 They're not simply at a Thread-granularity level, ie it is not a case of just calling wait() and being woken up by the next call to notify() . 它们不仅仅处于线程粒度级别,即它不是仅调用wait()并且在下一次调用notify()被唤醒的情况。 Rather, you always call wait() on a specific object, and will only be woken by calls to notify on that object . 相反,您始终对特定对象调用wait() ,并且只会通过对该对象进行notify的调用来唤醒。

This is good because otherwise concurrency primitives just wouldn't scale; 这很好,因为否则并发原语就不会扩展; it would be equivalent to having global namespaces, since any calls to notify() anywhere in your program would have the potential to mess up any concurrent code as they would wake up any threads blocking on a wait() call. 它等同于具有全局命名空间,因为在程序中的任何地方调用notify()都有可能弄乱任何并发代码,因为它们会唤醒在wait()调用上阻塞的任何线程。 Hence the reason that you call them on a specific object; 因此你在特定对象上调用它们的原因; it gives a context for the wait-notify pair to operate on, so when you call myBlockingObject.notify() , on a private object, you can be sure that you'll only wake up threads that called wait methods in your class. 它为wait-notify对提供了一个上下文,因此当你在私有对象上调用myBlockingObject.notify() ,你可以确定你只会唤醒在你的类中调用wait方法的线程。 Some Spring thread that might be waiting on another object will not be woken up by this call, and vice versa. 一些可能在另一个对象上等待的Spring线程将不会被此调用唤醒,反之亦然。

Edit: Or to address it from another perspective - I expect from your question you thought you would get a handle to the waiting thread and call notify() on that Thread to wake it up. 编辑:或者从另一个角度解决它 - 我希望你的问题,你认为你会得到一个等待线程的句柄,并在该线程上调用notify()来唤醒它。 The reason it's not done this way, is that you would have to do a lot of housekeeping yourself. 它没有这样做的原因是你必须自己做很多家务。 The thread going to wait would have to publish a reference to itself somewhere that other threads could see it; 要等待的线程必须在其他线程可以看到的地方发布对自己的引用; this would have to be properly synchronized to enforce consistency and visibility. 这必须正确同步以强制一致性和可见性。 And when you want to wake up a thread you'd have to get hold of this reference, awaken it, and remove it from wherever you read it from. 当你想要唤醒一个线程时,你必须抓住这个引用,唤醒它,并从你读取它的任何地方删除它。 There's a lot more manual scaffolding involved, and a lot more chance of going wrong with it (especially in a concurrent environment) compared to just calling myObj.wait() in the sleeping thread and then myObj.notify() in the waker thread. 还有很多更多的手动脚手架参与,并与刚刚调用的脚麻它(尤其是在并发环境中)有很多更多的机会myObj.wait()在休眠线程,然后myObj.notify()在waker的线程。

The most simple and obvious reason is that any Object (not just a thread) can be the monitor for a thread. 最简单明了的原因是任何Object(不仅仅是一个线程)都可以作为线程的监视器。 The wait and notify are called on the monitor. 在监视器上调用wait和notify。 The running thread checks with the monitor. 正在运行的线程检查监视器。 So the wait and notify methods are in Object and not Thread 所以wait和notify方法是在Object而不是Thread

Because only one thread at a time can own an object's monitor and this monitor is what the threads are waiting on or notifying. 因为一次只有一个线程可以拥有对象的监视器,并且此监视器是线程正在等待或通知的内容。 If you read the javadoc for Object.notify() and Object.wait() it's described in detail. 如果您阅读了Object.notify()Object.wait()javadocObject.notify()详细介绍它。

The mechanism of synchronization involves a concept - monitor of an object. 同步机制涉及一个概念 - 对象的监视。 When wait() is called, the monitor is requested and further execution is suspended until monitor is acquired or InterruptedException occurs. 调用wait()时,将请求监视器并暂停执行,直到获取监视器或发生InterruptedException。 When notify() is called, the monitor is released. 调用notify()时,将释放监视器。

Let's take a scenario if wait() and notify() were placed in Thread class instead of Object class. 如果将wait()和notify()放在Thread类而不是Object类中,那么我们来看一个场景。 At one point in the code, currentThread.wait() is called and then an object anObject is accessed. 在代码中的某一点,调用currentThread.wait() ,然后访问对象anObject

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

When currentThread.wait() is called, monitor of currentThread is requested and no further execution is made until either the monitor is acquired or InterruptedException occurs. 当调用currentThread.wait()时,将请求监视currentThread ,并且在获取监视器或发生InterruptedException之前不再执行任何操作。 Now while in waiting state, if a method foo() of another object anotherObject residing in currentThread is called from another thread, it is stuck even though the called method foo() does not access anObject . 现在处于等待状态时,如果从另一个线程调用驻留在currentThread的另一个对象anotherObject的方法foo() ,即使被调用的方法foo()不访问anObject ,它也会被卡住。 If the first wait() method was called on anObject , instead of the thread itself, other method calls (not accessing anObject ) on objects residing in the same thread would not get stuck. 如果在anObject调用第一个wait()方法而不是线程本身,则驻留在同一线程中的对象上的其他方法调用(不访问anObject )不会被卡住。

Thus calling wait() and notify() methods on Object class(or its subclasses) provides greater concurrency and that's why these methods are in Object class, not in Thread class. 因此,在Object类(或其子类)上调用wait()和notify()方法可以提供更高的并发性,这就是为什么这些方法在Object类中,而不是在Thread类中。

A few of the other answers use the word "monitor", but none explain what it means. 其他一些答案使用“监视器”一词,但没有一个解释它的含义。

The name "monitor" was coined way back in the 1970s, and it referred to an object that had its own intrinsic lock, and associated wait/notify mechanism. 名称“monitor”是在20世纪70年代创造的,它引用了一个具有自己的内部锁定和相关的等待/通知机制的对象。 https://en.wikipedia.org/wiki/Monitor_%28synchronization%29 https://en.wikipedia.org/wiki/Monitor_%28synchronization%29

Twenty years later, there was a brief moment in time when desktop, multi-processor computers were new, and it was fashionable to think that the right way to design software for them would be to create object-oriented programs in which every object was a monitor. 二十年后,台式机,多处理器计算机出现了新的短暂时刻,认为为他们设计软件的正确方法是创建面向对象的程序,其中每个对象都是监控。

Turns out not to have been such a useful idea, but that brief moment happens to be exactly when the Java programming language was invented. 事实证明这并不是一个有用的想法,但这个短暂的时刻恰好恰好是Java编程语言的发明时期。

Read here for an explanation of wait and notify. 请阅读此处以获取等待和通知的说明。

It would be better to avoid these however in your applications and use the newer java.util.concurrent package. 最好在应用程序中避免使用这些并使用较新的java.util.concurrent包。

I will put it in a simple way: 我将以简单的方式说:

To call wait() or notify() you need to own the object monitor - this means wait() or notify() needs to be present in the synchronized block 要调用wait()或notify(),您需要拥有对象监视器 - 这意味着wait()或notify()需要出现在synchronized块中

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

Thats the reason these methods are present in object class 这就是这些方法存在于对象类中的原因

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

Wait and Notify methods are used communication between two Threads in Java. Wait和Notify方法用于Java中两个Thread之间的通信。 So Object class is correct place to make them available for every object in Java. 所以Object类是正确的位置,使它们可用于Java中的每个对象。

Another reason is Locks are made available on per Object basis. 另一个原因是锁定是基于每个对象提供的。 Threads needs lock and they wait for lock, they don't know which threads holds lock instead they just know the lock is hold by some thread and they should wait for lock instead of knowing which thread is inside the synchronized block and asking them to release lock 线程需要锁定并等待锁定,他们不知道哪些线程持有锁而不知道锁定是否被某个线程保持并且他们应该等待锁定而不是知道哪个线程在同步块内并要求它们释放锁

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM