Java 5 and above only. Assume a multiprocessor shared-memory computer (you're probably using one right now).
Here is a code for lazy initialization of a singleton:
public final class MySingleton {
private static MySingleton instance = null;
private MySingleton() { }
public static MySingleton getInstance() {
if (instance == null) {
synchronized (MySingleton.class) {
if (instance == null) {
instance = new MySingleton();
}
}
}
return instance;
}
}
Does instance
have to be declared volatile
in order to prevent the optimizer from rewriting getInstance() as follows (which would be correct in a sequential program):
public static MySingleton getInstance() {
if (instance == null) {
synchronized (MySingleton.class) {
// instance must be null or we wouldn't be here (WRONG!)
instance = new MySingleton();
}
}
}
Assuming the optimizer does not rewrite the code, if instance
is not declared volatile
is it still guaranteed to be flushed to memory when the synchronized
block is exited, and read from memory when the synchronized
block is entered?
EDIT: I forgot to make getInstance() static. I don't think that changes the validity of the answers; you all knew what I meant.
javap -c com.example.ClassName
to disassemble the code so that you can check how it has been compiled and if the compiler has changed/optimized the one or other. I checked it for you with the one of JDK 1.6 and the compiler didn't strip out the nestedif
. – Stableboy