Skip to content
Advertisement

java – synchronization and volatile variable

I’ve read from this article that:

…Synchronized blocks also guarantee that all variables accessed inside the synchronized block will be read in from main memory, and when the thread exits the synchronized block, all updated variables will be flushed back to main memory again, regardless of whether the variable is declared volatile or not.

There’s also an example showed in Effective Java:

JavaScript

The variable stopRequested is not declared as volatile and the author states that “…In other words, the synchronization on these methods is used solely for its communication effects, not for mutual exclusion…”. But I would like to know that, in case of accessing an element of an array or accessing a field of an object in a synchronized method/block, could we always guarantee the memory visibility, without having to manually force a volatile access of the array’s element (by using Unsafe#getObjectVolatile for example) or declare the volatile modifier on the object’s field? Thanks!

JavaScript
JavaScript

Advertisement

Answer

In the first example, flags is initialised using a static initialiser. It is guaranteed by the Java Memory Model that any subsequent reads would see the updated value of the reference, and the correct initial state of Flags (basically, Flags would be properly published).

However, since Flags is mutable and might be mutated at a later point in time by multiple threads, you need to use proper synchronisation to ensure memory visibility for its state. So a volatile would be needed for its fields (or proper synchronisation).

In the second example, simply declaring flags as volatile won’t ensure memory visibility of writes to arrays. It just ensures a happens-before relationship b/w writes to the array reference and subsequent reads from it. To ensure a happens-before relationship b/w writes to array elements and subsequent reads from them, you need to use locking, which you are already doing.

Why this works? The JMM guarantees a happens-before relationship b/w the release of a monitor and its re-acquisition. When a thread releases a lock which is later acquired by another thread, a kind-of total ordering (governed by happens-before) is ensured b/w whatever writes happened in the previous thread and any subsequent reads by the thread that re-acquired the lock.

Just remember that declaring a reference as volatile does not ensure proper visibility of the mutable state of the object it refers to. We still need proper synchronisation mechanisms to ensure memory visibility.

Advertisement