简体   繁体   中英

Confusing reason for thread waking up when condition does not hold

I am currently reading Effective Java and I am on the concurrency chapter. While explaining reasons a thread might wake up when a condition doesn't hold (condition of while loop in which a wait() call abides) there is one reason that is pretty confusing to me and I can't seem to understand it.

Another thread could have obtained the lock and changed the guarded state between the time a thread invoked notify and the waiting thread woke up.

Can someone try to explain this sentence?

This is easiest to explain with an example:

public class ConditionTest implements Runnable {
    
    private boolean flag;
    
    public void run() {
        try {
            synchronized (this) {
                while (true) {
                    this.wait();
                    if (flag) {
                        System.out.printf("%s: my condition is true\n",
                                          Thread.currentThread().getName());
                        flag = false;
                    } else {
                        System.out.printf("%s: my condition is false!!\n",
                                          Thread.currentThread().getName());
                    }
                }
            }
        } catch (InterruptedException ex) {
             // bail out
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        ConditionTest ct = new ConditionTest();
        new Thread(ct).start();
        new Thread(ct).start();
        new Thread(ct).start();
    
        Thread.sleep(1000);
    
        while (true) {
            synchronized(ct) {
                ct.flag = true;
                ct.notifyAll();
            }
            Thread.sleep(1000);
        }
    }
}

The condition in this example is that the runnable's flag should be true . The worker threads report the state of the condition and then clear the flag.

As you can see, the main method created and starts three threads sharing a runnable. Then it repeatedly sets the flag to true and notifies the workers.

When a worker is woken, it may find that the flag is false ; ie its condition does not hold. In fact, if you run the above code, you will see that it happens two times out of three.

Why?

Because, if a worker sees that flag == true , it clears the flag! So when the other workers wake up, they see the cleared flag.

This is the kind of thing that the quoted text is talking about.

Admittedly, in this case it is caused by our dubious notifyAll call, but the general principle applies. You should check the condition.


It also is (or was) possible on some platforms for spurious notifications to happen; ie notifications that are not the result of any notify or notifyAll call from application code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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