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

2022-01-22 00:00:00 wait synchronization java notify

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

I was getting java.lang.IllegalMonitorStateException. I referred this question and it solved my problem. The first answer is

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();
}  

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

就我的理解而言,当我们说

As far as my understanding goes when we say

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

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

we get a lock on object someObject and then we call wait() on it. Now how can another thread get lock on same object to call notify() on it? What am I missing?

推荐答案

为什么notify也需要锁?

Why does notify need a lock too?

想象一下这个场景:

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

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

Imagine now a notify elsewhere without any lock around it:

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

乍一看,整个声音总是按预期工作.
但是,想象一下这种竞争条件:

At first glance, the whole sounds to always work as expected.
However, imagine this race condition:

//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 方:

If only we had a way to tell this to notify side:

线程 1:嗯..notify,你很可爱,但我刚刚开始评估我的条件 (x.count < 4) 是否为真,所以请......不要傻傻的发送你预期的通知(在我将我的状态置于等待之前),否则,我等待已经过去的事情会很荒谬"

Thread 1: "Humm..notify, you are cute but I've just started to evaluate my condition (x.count < 4) to true, so please... don't be silly by sending your expected notification just now (before I put my status to waiting), otherwise, I would be ridiculous to wait for a thing that already passed"

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

Thread2: "Ok ok... I will put a lock around my logic in order to stay consistent, so that I send my notification after your wait call releases our shared lock, and thus you will receive this notif, allowing to quit your waiting status ;)"

因此,总是在 notify 端,在等待持有的同一个对象上加一个锁,以避免这种情况,让关系始终保持一致.

Thus, always place a lock on the notify side, on the same object that is hold by wait, in order to avoid this situation and let the relationship always consistent.

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

=> A logic leading to a notify and a logic leading to a wait should never overlap.

相关文章