Thursday, January 28, 2016

Java Singleton Design Pattern: Double check lock

Java Singleton Design Pattern tells us to have a single copy of Java Object in memory throughout its execution life time.

In Java, it can be achieved by various ways but in Multi-threaded system, one of the beautiful ways to achieve this by applying double check locking. This will ensure faster and efficient way in multi-threaded environment.

Locking via synchronizing method:
Yes Singleton Design pattern in Java can also be achieved by synchronizing method but its inefficient.

Here is an example:

public class Singleton {
private static Singleton pattern = null;

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

Consider there are many threads trying to call getInstance method. Only one can acquire lock and rest will have to wait till the first one releases it (even for fetching this object). This makes it too inefficient in Multi-threaded environment.

Double Check Locking:
Consider below code snippet example for double Null check and locking for Singleton Design Pattern.

public class Singleton {
private static Singleton design = null;

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

The above code is most optimized for Multi-threaded system. The first null check is essential after Singleton object has already been created by first thread entering the synchronized block and hence getting the instance of this object does not have to deal with acquiring lock by each thread.

Why second null check :
Ever wondered why you need to check object reference null again after acquire lock (as it has already been checked before acquiring lock). Consider the case where two or more threads passes first null check barrier and only one thread enters the lock, while making other waiting for that lock. When the first thread releases the lock after giving call to object creation, the rest others thread will not be aware of object creation and will go and acquire lock and create object (as it has already executed first null check when there is no object created). This will result in creating more than one IAmSingle object breaking the purpose of singleton design pattern.

Everything fine with above code?
So, does the above code is full proof of creating Single Object in Multi-threaded environment. Well actually its not. Any guess?

Well the answer lies hidden in way Java Virtual Machine creates object in heap memory area. To achieve optimization, JVM give instruction to create object and the code flows continues. It might happen (very rarely) while object is in process of being created, the next thread acquires lock and have passed call to second null check!!!!!! resulting in two objects being created!!!

Fix / Solution: 
For Java 5 and later, making the reference variable volatile will fix the above problem. This has been possible due to change in the way volatile works in Java 5. With Java 5, it is guaranteed that the write to a volatile field happens-before every subsequent read of that same volatile and hence no next read will get half baked / null singleton object (https://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html)

Volatile vs Synchronized performance overhead:
Now since volatile is required to work multithreaded singleton design pattern, there has been a long debate that there is no performance advantage if we use volatile over synchronized call. Please note that volatile is cheap as compared to using synchronized overhead.