Code Pumpkin

Singleton Design Pattern Using Double Checked Locking

This is our second article in the series of Singleton Design Pattern.  In this article, we will see different thread safe approaches for lazy Initialization Singleton Design Pattern like Using Synchronized getInstance() methodDouble checked locking approach and Bill Pugh Implementation using Inner class.

For navigating to the other articles on Singleton Design Pattern, please refer table of contents on the right side.

In our previous article, we have seen Eager Initialization,  Static Block Initialization and Lazy Initialization for implementing singleton design pattern. Among these three, lazy initialization approach is not thread safe. Lets have a look at the code for basic Lazy Initialization approach:



public class LazzyInitializedSingleton {

	private static LazzyInitializedSingleton instance;

	private LazzyInitializedSingleton() {

	}

	// Lazy initialization is done when client first time request for the instance
	public static LazzyInitializedSingleton getInstance() {
		if (instance == null) {
			instance = new LazzyInitializedSingleton();
		}
		return instance;
	}
}

Download Complete Java Program »

Lazy Initialization implementation will work when the given environment is single threaded. However in multithreaded environment, above code may create more than one instance. For example,

  • Assume that two threads T1 and T2 are calling getInstance() method concurrently.
  • Thread T1 has checked the null condition on line 11 and entered inside if block as no instance has been created yet. 
  • Now T1 is inside the if condition, but it has not created instance yet. At the same time another thread T2 reaches to the null condition on line 11. As instance is still null, T2 also enters the if condition.
  • Now both threads will create instance on line 12 which will break the singleton design pattern.

Here is the graphical representation for the same :

Using synchronized getInstance() method – Naive Approach

So how can we prevent creation of multiple instances in above approach? Easiest way to achieve this is by making getInstance() method thread-safe using synchronized keyword as shown below.



public class ThreadSafeSingleton {
	private static ThreadSafeSingleton instance;

	private ThreadSafeSingleton() {
	}

	// Thread T2, T3, T4 are waiting for T1 to release the lock
	public static synchronized ThreadSafeSingleton getInstance() {
		// Thread T1 has taken the lock
		if (instance == null) {
			instance = new ThreadSafeSingleton();  // Critical section
		}
		return instance;
	}
}

Download Complete Java Program »

This will solve our problem. But it leads us to bad performance as only one thread can access getInstance() method at a time even though critical section is only one line (line 11) where instance is being created. 

For Example, In above code, as Thread T1 is inside getInstance() method, other threads T2, T3, T4 has to wait until T1 completes its execution of getInstance() method. It reduces performance drastically. 


Double Checked Locking

In above approach, we need to bear cost of synchronization all the time we call getInstance() method,  but synchronization is only needed on first call when Singleton instance is created.

To improve the performance, lets modify the code of getInstance() method. Instead of declaring entire method synchronized, now we will just include critical section inside synchronized block as shown below:



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

	}
	return instance;
}

Will this improve the performance?

Yes. If instance has already been created, then threads will not enter the if block and directly return instance. They don't have to wait for lock on synchronized block.

Is it thread-safe? Can you think of any situation which can result into creation of multiple instances?

Here is the case in which singleton design pattern will break with this approach :

This will bring us to double checked locking pattern, where we will also add one more null check inside synchronized block as shown below.



package com.codepumpkin.creational.singleton;

public class DoubleCheckedLockingSingleton {

    // this field should be volatile to avoid half baked object creation
	private static DoubleCheckedLockingSingleton instance;   

	private DoubleCheckedLockingSingleton() 
	{
       // 10000 lines of initialization code
	}

	public static DoubleCheckedLockingSingleton getInstance() 
	{
		if (instance == null) 
		{
			synchronized (DoubleCheckedLockingSingleton.class) 
			{
				if (instance == null) 
				{
					instance = new DoubleCheckedLockingSingleton();
					System.out.println("Instance Created");
				}
			}

		}
		return instance;
	}

}

Download Complete Java Program »

Programmers call it double checked locking because there are two checks for (instance == null), one without locking and other with locking i.e. inside synchronized block.

This approach improves performace as threads do not have to wait for lock if object is already created. Also there is no chance of multiple object creation as we are having null check inside synchronized block as well.


Half Baked Object – Issue with Double Checked Locking

Above code looks perfectly fine and it should work correctly, right? Unfortunately, there is no guarantee it will work correctly on all JVM and it may fail in some.  

Issue is not with the JVM or our code, but it is with the Java Memory model and the way java code compiles using some of the JIT Compilers. The Java memory model allows what is known as "out-of-order writes" and it is a prime reason for this issue.


What is "out-of-order writes"?

To understand this better, lets look at the process of object creation in Java. Here are the steps which are being followed by most of the compilers.

  1. Allocating a memory to the object
  2. execute the code inside constructor 
  3. Assigning memory reference to the field

Problem is with some of the JIT compilers which reorders step 2 and step 3 in above instructions. To understand how this occurs, consider the following pseudo code for the line:



instance = new DoubleCheckedLockingSingleton();

Pseudo Code



//Allocate memory for Singleton object.
mem = allocate();             

//Note that instance is now non-null, but has not been initialized. 
instance = mem;              

//Invoke constructor for Singleton passing instance.
invokeDoubleCheckedLockingSingletonConstructor(instance); 

So, when object will be created, instance variable will be assigned non-null reference and then rest of the code inside constructor will be executed.

What is Half Baked Object?

If Object was assigned non-null reference and code inside that constructor is still being executed, then that object is not fully constructed or baked and is referred as Half Baked Object.

How Double Checked Locking pattern returns Half Baked Object?

Refer Below code. I have replaced line instance = new DoubleCheckedLockingSingleton();  with pseudo code for better understanding.



public static DoubleCheckedLockingSingleton getInstance() 
{
	if (instance == null)   // Thread T2 
	{
		synchronized (DoubleCheckedLockingSingleton.class) 
		{
			if (instance == null) 
			{
				// pseudo code for instance = new DoubleCheckedLockingSingleton();
				mem = allocate();             
				instance = mem;              
				invokeDoubleCheckedLockingSingletonConstructor(instance);  // Thread T3
			}
		}
	}
	return instance;
}

Assume that Thread T1 is executing line 12 i.e. it has assigned non-null reference to instance variable, but it has not completed executing code written inside constructor.

At the same time Thread T2 entered getInstance() method and reached at line 3 i.e. outer null-check. As instance is already been assigned, it will not enter the if block and returns half baked object.

Solution to Half Baked Object Issue using volatile

Above problem can be solved by declaring instance field as volatile. However, it will not work in JDK 1.4 and earlier versions.



private static volatile DoubleCheckedLockingSingleton instance;

In JDK 1.5, Some modifications were done in Java Memory Model and behavior of volatile and final fields. From JDK 1.5, The volatile prevents memory writes from being re-ordered, making it impossible for other threads to read uninitialized fields of your singleton through the singleton's pointer.

In other words, when field is declared as volatile, JVM guarantees completion of all those three steps of object creation (refer pseudo code) before another thread reads the reference from instance variable.  This is also known as Happens-Before relationship of volatile field which was introduced in JDK 1.5.


Bill Pugh Singleton Implementation using Inner class

Is there any way by which we can create singleton object lazily without facing issue of multithreading? 

Well answer is yes. Bill Pugh came up with a different approach to create the Singleton class using a inner static helper class as shown below:



public class BillPughSingleton {

    private BillPughSingleton(){}
    
    private static class SingletonHelper{
        private static final BillPughSingleton INSTANCE = new BillPughSingleton();
    }
    
    public static BillPughSingleton getInstance(){
        return SingletonHelper.INSTANCE;
    }
}

Download Complete Java Program »

Notice the private inner static class SingletonHelper that contains the instance of the BillPughSingleton class. When the BillPughSingleton class is loaded, SingletonHelper class is not loaded into memory and only when someone calls the getInstance() method, this class gets loaded and creates the BillPughSingleton class instance. 

So it may seem like eager initialization but it is lazy initialization and we don't even required to deal with complex thread-safety mechanism.


Next Article in the series of Singleton Design Pattern :  Preventing Cloning In Singleton Design Pattern

That's all for this topic. If you guys have any suggestions or queries, feel free to drop a comment. We would be happy to add that in our post. You can also contribute your articles by creating contributor account here.

Happy Learning 🙂

About Abhi Andhariya

Surviving Java Developer, Passionate Blogger, Table Tennis Lover, Bookworm, Occasional illustrator and a big fan of Joey Tribbiani, The Walking Dead and Game of Thrones...!!

Tags: , , , , , , , ,


Comments and Queries

If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code class="java"> 
String foo = "bar";
</code></pre>
For more information on supported HTML tags in disqus comment, click here.
Total Posts : 96
Contribute Your Articles

Subscribe Us

Like Us On Facebook