According to Java Concurrency in Action if we have the following class:
public class Wrapper { private int num; public Wrapper(int num) { this.num = num; } public void assertCorrectness() { if (num != num) throw new AssertionError("This is false"); } }
and we initialise an instance of this class and publish it in a non-safe way (through a simple public field for example), then the assertCorrectness() might indeed throw an AssertionError, if called from another thread. In other words, this means that some another thread might see an up-to-date reference to the instance, but the state of the instance itself could be out-of-date (so a thread can see an object exists but it is in a partially constructed / inconsistent state).
On the other hand, it is said that publishing an instance of this class through a volatile reference is considered safe. However it was my understanding that volatile just guarantees that any thread will always see an up-to-date version of a reference, but not the object’s state being referenced. So we can be sure that if one thread assigns a new instance of the Wrapper class to a volatile field, then all the other threads will see that the reference was updated. But is there a risk that they will still see an object in an inconsistent / partially constructed state?
Advertisement
Answer
No, because volatile
being used establishes a happens-before relationship. Without it various reorderings and other things are allowed, which make the inconsistent state possible, but with it the JVM must give you the expected outcome.
In this case volatile
is not used for the visibility effects (threads seeing up to date values), but the safe publishing provided by the happpens-before. This feature of volatile
is often left out when its use is explained.