Thursday, June 16, 2011

Lock-less singleton pattern

Although the singleton pattern is now know as an anti-pattern, I think it still is a valid choice when you only need one instance in a particular context. Anyway, in Java there are several ways to implement a singleton.

For example this one uses a synchronized block:

private Singleton singleton = null; protected Singleton createSingleton() { synchronized (this) { // locking on 'this' for simplicity if (singleton == null) { singleton = new Singleton(); } return singleton; } }

To prevent locking all the time you can use the double-check idiom on a modern JVM. But I just thought about another implementation that switches locking for preventing code re-ordering, making it a lock-less implementation:

private AtomicReference singletonRef = new AtomicReference(null); protected Singleton createSingleton() { Singleton singleton = singletonRef.get(); if (singleton == null) { singleton = new Singleton(); if (!singletonRef.weakCompareAndSet(null, singleton)) { singleton = singletonRef.get(); } } return singleton; }

There is only one catch to this implementation: although createSingleton() will always return the same instance, it must be allowed to call the constructor of Singleton twice without side-effects.

Update 2011-06-18: changed compareAndSet to weakCompareAndSet as suggested by Adriano.


  1. Might be worth adding that double checked locking on the JVM has been known to have some very subtle issues:

  2. Will, that's old news. At your link please look up the section 'Under the new Java Memory Model'.

    In fact my implementation doesn't differ that much from using a volatile. The only difference is that the locking (the synchronized block) is replaced by a compare and swap instruction.

  3. AFAIU, weakCompareAndSet could be used there to be fast.

    weakCompareAndSet atomically reads and conditionally writes a variable but does not create any happens-before orderings, so provides no guarantees with respect to previous or subsequent reads and writes of any variables *other than the target of the weakCompareAndSet*.

  4. Thanks Adriano, I was not aware of this. I'll update the article.

  5. I think it is also possible to use a AtomicReferenceFieldUpdater and a volatile field. I am not sure if this is faster than the AtomicReference.get().