Singleton Pattern and Problem With Double Checked Locking

There are several ways to initialize singleton object. Some are thread safe and some are not. Until the last two days I thought that double-checked locking idiom offers the best solution for singleton initialization in multi threaded environment. Well its not.

To begin, I want to describe briefly several ways to initialize singleton:

  • Lazy initialization
  • Eager initialization
  • DCL
  • Class holder lazy initialization
  • Enum singleton

Lazy initialization
The goal of lazy initialization was to defer initialization of an object until it is actually needed, while making sure that initialization is done only once. Lazy initialization example illustrated below:

public class Singleton{

	private static Singleton instance = null;

	private Singleton() {  }

	public static Singleton getInstance() {
		if (instance == null)  {
		instance = new Singleton();
	}
        return instance;
    }
}

This will work fine in single-threaded environment. Unfortunately since getInstance() is not synchronized, two different instances of the object can be returned if two threads will access getInstance() method concurrently. Which makes this lazy initialization unsafe in multi threaded environment.

Unsafe lazy initialization can be fixed by making getInstance() synchronized:


	public class Singleton{

	private static Singleton instance = null;

	private Singleton() {  }

	public static synchronized Singleton getInstance() {
		if (instance == null)  {
			instance = new Singleton();
		}
		return instance;
	}
	}

However, in this case there is performance hit for every invocation of getInstance() method. Synchronized methods runs very slow compared to unsynchronized methods. I haven’t tested this issue my self, so i cannot tell by how much slower.

Eager initialization
By using eager initialization, the synchronization cost incurred for each method call is eliminated:

	public class Singleton{
		private static Singleton instance = new Singleton();

		private Singleton() {  }

		public static Singleton getInstance() {
			return instance;
		}
	}

The problem with eager initialization that Singleton object is instantiated regardless whether it is going to be used or not.

DCL
Double-checked locking (DCL) idiom was created to allow lazy initialization of a singleton object, without performance reducing costs as a result of synchronization. Unfortunately it does not work. Lets have a look why:

public class Singleton {

  private static Singleton instance = null;

  private Singleton() {  }

  public static Singleton getInstance() {
	if (instance == null)  {
		synchronized(Singleton.class)  {
			if (instance == null)  {
				instance = new Singleton();
			}
		}
	}
	return instance;
	}
}

First there is a check whether initialization is needed with out synchronization, and if the instance is not null – then use it.
Otherwise, synchronize and check again if instance is null by making sure that only one thread will initialize the shared Singleton.

The problem with DCL is that code of fetching reference to constructed Singleton object does not require synchronization.
Lets say that thread ‘a’ has entered synchronized block, made the instance not null but hasn’t executed the constructor yet. At this stage thread ‘b’ preempts thread ‘a’. Thread ‘b’ checks if the instance is not null, and since its not, it returns reference to a partially constructed Singleton object.

In other words – thread ‘b’ sees a current value of the Singleton object reference instead of its stale value, which causes the object to be seen in invalid or incorrect state.

Class holder lazy initialization

Instead of DCL, lazy initialization class holder idiom offers better solution for singleton initialization in multi threaded environment, with the same benefits as DCL:

public class SingletonFactory {

  private static class SingletonHolder {
     public static Singleton instance = new Singleton();
  }

  public static Singleton getInstance()  {
     return SingletonHolder.instance;
  }
}

The SingletonHolder class initialization is deferred until its actually used, and because Singleton is initialized with static initializer, no additional synchronization is needed.
The first invocation of getInstance() by any thread causes SingletonHolder to be loaded and initialized during which time the Singleton is initialized through static initializer.

Enum singleton
Joshua Bloch in his book “Effective Java” offers a new interesting solution to initialize a Singleton by using Enum with a single type:

public class SingletonEnum {
  INSTANCE;

  public void someMethod() {
     ...
  }

  public void anotherMethod() {
     ...
  }
}

Joshua claims:

“…a single-element enum type is the best way to implement a singleton…”

Some people may argue against this approach by saying that this is not a class, but an enum – it enumarates plus enums cannot be subclassed. Well in case of a singleton there is no point in subclassing, since singletons have private constructors and singletons dont really ment to be subclassed. Lets have a look if Enum singleton is indeed the best solution so far:

1. Enum singleton is final
2. It is serializable
3. It is a single instance in multithreaded environment
4. Does not allow invokation of private constructors through reflection attacks

I think its quite original solution.

I will appreciate your comments regarding this post. Cheers.

Resources:
Effective Java
Java Concurrency in Practice

Double-checked locking and the Singleton pattern

More from Alexander Zagniotov:

  1. Java Generics and Reflection
    Hi, the other day I had a situation, where in my code at run time I had to determine the...
  2. Marshalling VS Serialization
    The two terms are very very similar, and often treated the same. Quite few responds on various forums contradict each...
  3. JBoss Clustering – HASingleton Service
    Have you ever dealt with clustered singleton service? How to determine which cluster node is the master? Well, if I...
  4. JBoss Clustering – Shared State Across Cluster Partition
    Did you know that if you have a JBoss cluster, HA singletons service beans on each can share a common...
  5. Using Template to Deploy a JBoss Queue
    Currently I am involved in a project, where I have to use Velocity template engine to deploy queues and message-driven...

 

Comments
  • Anthony Balmein June 24, 2010 at 6:56 pm

    Thank you for the concised summary, good post.

    Anthony