Here is my singleton class.
Static instance
field is not volatile thus reordering/visibility problem arises. To solve it instance val
field is made final. Since instance is properly constructed its clients should always see val
field initialized if they see instance at all.
static class Singleton {
private static Singleton instance;
private final String val;
public Singleton() { this.val = "foo"; }
public static Singleton getInstance() {
if (instance == null)
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
return instance;
}
public String toString() { return "Singleton: " + val; }
}
However there is another problem - I've got two unprotected reads of "instance" field which can be(?) reordered so that client may get null instead of real value:
public static Singleton getInstance() {
Singleton temp = instance;
if (instance != null) return temp;
else { /* init singleton and return instance*/ }
}
To workaround this I feel like I can introduce local variable:
public static Singleton getInstance() {
Singleton temp = instance;
if (temp == null)
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
temp = instance;
}
}
return temp;
}
This seem to solve the problem since there is only one unprotected read of value so nothing really evil should happen. But... I've just modified the program flow without(almost?) changing its single threaded semantics. Does this mean that compiler can just undo my workaround since this transformation is safe and there is no way to make this code working without establishing proper happens-before relationship with volatile?