The Java memory model question 16 of 180 senior
Why does double-checked locking need the field to be volatile?
- To stop two threads entering the synchronized block
- Correct: Without it, another thread can see a non-null reference to an object whose constructor has not finished
- Because
synchronizeddoes not work on static fields - It is not needed since Java 8
instance = new Helper() is three steps: allocate, run the constructor, publish the reference. The
JIT is allowed to publish before the constructor finishes, because within the constructing thread
nothing can tell the difference. Another thread taking the fast path sees a non-null reference and
reads fields that are still at their defaults.
volatile forbids that reordering and gives the reader the acquire edge that makes the constructor's
writes visible. This was genuinely broken before Java 5, which is why the "broken DCL" folklore still
circulates.
private static volatile Helper instance; // volatile is the whole fix
static Helper get() {
Helper local = instance; // one volatile read on the fast path
if (local == null) {
synchronized (Helper.class) {
local = instance;
if (local == null) {
instance = local = new Helper();
}
}
}
return local;
}
For a static singleton, the holder idiom is simpler and needs no volatile at all: class initialisation is already synchronised by the JVM.