In Java Double checked locking (DCL) attempts to improve performance of lazy instantiation but without memory barriers is exposed to dangerous race conditions between the setting of a variable's address and the publishing of its value to main memory.
So my question is:
Can someone provide an example Java program/snippet, that reliably shows an incorrect value read as a result of DCL without volatile on the variable?
Here is my (failed ) attempt at it.
class Foo {
String field = null; // not volatile
String getField() {
if( field == null )
{
synchronized (this) {
if ( field == null )
field = new String("abc");
}
}
return field;
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
if ( !Example.foo.getField().equals("abc") ) {
System.out.println("Got an uninitialized FIELD !!!");
}
}
}
class Example {
static Foo foo;
public static void main(String[] args) throws InterruptedException {
for( int i = 0; i < 1000000; ++i ) {
foo = new Foo();
Thread t1 = new Thread(new MyRunnable());
Thread t2 = new Thread(new MyRunnable());
t1.start();
t2.start();
t1.join();
t2.join();
}
}
}
Obviously not being able to prove it doesn't mean that DCL is safe, but it would still be nice to have an obvious example that shows that it is dangerous.