Should the volatile modifier be added to the object wake-up condition variable?

Please check the sample code below:

private volatile int fActiveTestDeathCount;

synchronized void waitUntilFinished() {
        while (fActiveTestDeathCount < testCount()) {
            try {
                wait();
            } catch (InterruptedException e) {
                return; // ignore
            }
        }
    }

The above code can run normally, which is very easy to understand, but why the following code can also run normally?

private int fActiveTestDeathCount;

synchronized void waitUntilFinished() {
    while (fActiveTestDeathCount < testCount()) {
        ...
    }
}

I think that in a multi-threaded execution environment, each thread copies the fActiveTestDeathCount variable. If there is no additional volatile modifier, this variable is invisible to other threads, and the program should not work, but this is not the case.

I try to analyze whether it is that after the thread is awakened, it will automatically invalidate the variables in the thread's working memory, and then synchronize the data from the main memory? But this requires the support of memory barriers, which makes me a little confused.

1 answer

  • answered 2021-10-12 15:54 David Schwartz

    Here volatile is neither required nor sufficient.

    Why is it not sufficient? Because it won't stop a thread from checking fActiveTestDeathCount right before it is modified by another thread and then irrevocably deciding to wait for something that happened right after it checked.

    Why is it not required? Because synchronized already establishes a "happens before" relationship among any two threads accessing fActiveTestDeathCount.

    The whole point of wait is to provide an atomic "unlock and wait" operation to solve precisely this race condition.

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum