Is it correct implementation of lazy-initializing singleton using AtomicReference? If no – what are the possible issues?
import java.io.ObjectStreamException; import java.io.Serializable; import java.util.concurrent.atomic.AtomicReference; public class Singleton implements Serializable { private static final Singleton _instance = new Singleton(); private static AtomicReference<Singleton> instance = new AtomicReference<Singleton>(); private Singleton() { } public static Singleton getInstance() { if (instance.compareAndSet(null, _instance)) { synchronized (_instance) { _instance.init(); instance.set(_instance); } } return instance.get(); } private void init() { // do initialization } private Object readResolve() throws ObjectStreamException { return getInstance(); } }
Advertisement
Answer
No, this is bad:
public static Singleton getInstance() { // new "singleton" for every method call Singleton s = new Singleton(); ^^^^^^^^^^^^^^ if (instance.compareAndSet(null, s)) { synchronized (s) { s.init(); } } return instance.get(); }
Using an AtomicReference is a nice idea, but it won’t work because Java doesn’t have lazy evaluation.
The classic post 1.5 singleton methods are:
Eager Singleton:
public final class Singleton{ private Singleton(){} private static final Singleton INSTANCE = new Singleton(); public Singleton getInstance(){return INSTANCE;} }
Lazy Singleton with inner holder class:
public final class Singleton{ private Singleton(){} private static class Holder{ private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance(){return Holder.INSTANCE;} }
Enum Singleton:
public enum Singleton{ INSTANCE; }
You should probably stick with one of these