java - 为什么我们需要在同一个对象上同步 notify() 才能工作

标签 java synchronization wait notify

我遇到了 java.lang.IllegalMonitorStateException。我提到了this问题,它解决了我的问题。第一个答案是

To be able to call notify() you need to synchronize on the same object.

synchronized (someObject) {
    someObject.wait();
}

/* different thread / object */
synchronized (someObject) {
    someObject.notify();
}  

我的问题是为什么我们需要在同一个对象广告上同步它是如何工作的?

据我所知,当我们说

synchronized (someObject) {
    someObject.wait();
}

我们在对象 someObject 上获得了一个锁,然后我们在它上面调用了 wait() 。 现在,另一个线程如何锁定同一个对象以对其调用 notify()?我错过了什么?

最佳答案

为什么 notify也需要锁?

想象一下这个场景:

synchronized(x){
        while(x.count < 4) {
          x.wait();
          //...
        }
}

现在想象一个 notify其他地方没有任何锁:

//...
println(x.count); // print 3
x.count++;
if(count == 4) 
  x.notify()
//...

乍一看,整体听起来总是按预期工作。
然而,想象一下这个竞争条件:

//Thread1 enters here
synchronized(x){
     while(x.count < 4) {
         //condition is judged true and thread1 is about to wait 
         //..but..ohh!! Thread2 is prioritized just now !
         //Thread2, acting on notify block side, notices that with its current count incrementation, 
         //count increases to 4 and therefore a notify is sent.... 
         //but...but x is expected to wait now !!! for nothing maybe indefinitely !
       x.wait();
       //maybe block here indefinitely waiting for a notify that already occurred!
     }
}

要是我们有办法告诉 notify 就好了边:

线程 1:“嗯.. notify,你很可爱,但我刚刚开始评估我的条件 (x.count < 4) 为真,所以请......不要傻傻地发送你期望的通知只是现在(在我把我的状态设置为等待之前),否则,我等待一个已经过去的事情是可笑的”

Thread2:“好的,好的...我将锁定我的逻辑以保持一致,以便我在您的等待调用释放我们的共享锁后发送我的通知,因此您将收到此通知,允许您退出等待状态;)"

因此,始终锁定 notify side,在wait持有的同一个对象上,为了避免这种情况,让关系一直保持一致。

=> 导致 notify 的逻辑和导致 wait 的逻辑不应重叠。

关于java - 为什么我们需要在同一个对象上同步 notify() 才能工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18095306/

相关文章:

Java SE 内存管理与 Scala 内存管理

java - 如何在java中多个字符串,包括乘以0

c++ - 如何跨不同分支同步Cuda?

synchronization - CPU 中的相关负载重新排序

.net - .NET 的分布式锁管理器 (DLM)?

javascript - jQuery 中的计时/等待

javascript - jQuery : wait until all ajax calls finish then continue

java - Java 两个命令之间的延迟? - 游戏

java - 停止maven安装

java - 通过 javax 拦截器记录用户的 session ID