I was reading an essay, which actually talks about double-checked locking, but I'm surprised about an even more basic failure in the code presented as examples. It is stated there that it is possible that the initialization of an instances (i.e. writes to the instance variables that happen before the constructor returns) may be reordered to after a reference to the instance is written to a shared variable (a static field in the following example).
Is it true that with the following definition of class Foo
, with one thread executing Foo.initFoo();
and a different thread executing System.out.println(Foo.foo.a);
, the second thread may print 0
(instead of 1
or throwing a NullPointerException
)?
class Foo {
public int a = 1;
public static Foo foo;
public static void initFoo() {
foo = new Foo();
}
public static void thread1() {
initFoo(); // Executed on one thread.
}
public static void thread2() {
System.out.println(foo.a); // Executed on a different thread
}
}
From what I know about the Java memory model (and memory models in other languages) it actually doesn't surprise me that this is possible but intuition is voting very strongly for it being impossible (maybe because object initialization is involved and object initialization seems so sacred in Java).
Is it possible to "fix" this code (i.e. that it will never print 0
) without synchronization in the first thread?