public class Singleton {
private static Singleton instance;
private final Singleton() {};
public static Singleton synchronized getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
Double check locking Singleton pattern
public class Singleton {
private static Singleton instance;
private final Singleton() {};
private static Object key;
public static Singleton getInstance() {
if (instance != null) {
return instance; // 1
}
synchronized(key) { // 2
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
}
in (1) the read is not synchronized or volatile => non synchronized read
in (2) the write is synchronized => synchronized write
Do we have a guarantee that the read will get the value set by write?
public class Singleton {
private static volatile Singleton instance; // THIS IS A FIX! (volatile)
private final Singleton() {};
private static Object key;
public static Singleton getInstance() {
if (instance != null) {
return instance;
}
synchronized(key) {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
}
Enum solution
public enum Singleton {
INSTANCE
}
Since the read of instance is synchronized => it cannot be made in parallel => in multicore world this is already a bad (non-performant) implementation of Singleton
There is a bug in this implementation
for this we need happens before link
But the fix by making an instance volatile costs the same performance prise as in synchronized Pattern above.