Friday, October 30, 2015

DCL singelton



Why you need Double checked Locking of Singleton Class?

One of the common scenario, where a Singleton class breaks its contracts is multi-threading. If you ask a beginner to write code for Singleton design pattern, there is good chance that he will come up with something like below :

private static Singleton _instance;

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

and when you point out that this code will create multiple instances of Singleton class if called by more than one thread parallel, he would probably make this whole getInstance() method synchronized, as shown in our 2nd code example getInstanceTS() method. Though it’s a thread-safe and solves issue of multiple instance, it's not very efficient. You need to bear cost of synchronization all the time you call this method, while synchronization is only needed on first class, when Singleton instance is created. This will bring us to double checked locking pattern, where only critical section of code is locked. Programmer call it double checked locking because there are two checks for _instance == null, one without locking and other with locking (inside synchronized) block. Here is how double checked locking looks like in Java :

public static Singleton getInstanceDC() {
        if (_instance == null) {                // Single Checked
            synchronized (Singleton.class) {
                if (_instance == null) {        // Double checked
                    _instance = new Singleton();
                }
            }
        }
        return _instance;
}


Double Checked Locking on Singleton in Java
On surface this method looks perfect, as you only need to pay price for synchronized block one time, but it still broken, until you make _instance variable volatile. Without volatile modifier it's possible for another thread in Java to see half initialized state of _instance variable, but with volatile variable guaranteeing happens-before relationship, all the write will happen on volatile _instance before any read of _instance variable. This was not the case prior to Java 5, and that's why double checked locking was broken before. Now, with happens-before guarantee, you can safely assume that this will work. By the way this is not the best way to create thread-safe Singleton, you can use Enum as Singleton, which provides inbuilt thread-safety during instance creation. Another way is to use static holder pattern.

/*
 * A journey to write double checked locking of Singleton class in Java.
 */

class Singleton {

    private volatile static Singleton _instance;

    private Singleton() {
        // preventing Singleton object instantiation from outside
    }

    /*
     * 1st version: creates multiple instance if two thread access
     * this method simultaneously
     */

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

    /*
     * 2nd version : this definitely thread-safe and only
     * creates one instance of Singleton on concurrent environment
     * but unnecessarily expensive due to cost of synchronization
     * at every call.
     */

    public static synchronized Singleton getInstanceTS() {
        if (_instance == null) {
            _instance = new Singleton();
        }
        return _instance;
    }

    /*
     * 3rd version : An implementation of double checked locking of Singleton.
     * Intention is to minimize cost of synchronization and  improve performance,
     * by only locking critical section of code, the code which creates
 instance of Singleton class.
     * By the way this is still broken, if we don't make _instance volatile,
 as another thread can
     * see a half initialized instance of Singleton.
     */

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

That's all about double checked locking of Singleton class in Java. This is one of the controversial way to create thread-safe Singleton in Java, with simpler alternatives available in terms of using Enum as Singleton class. I don't suggest you to implement your Singleton like that as there are many better way to implement Singleton pattern in Java. Though, this question has historical significance and also teaches how concurrency can introduce subtle bugs. As I said before, this is very important from interview point of view. Practice writing double checked locking of Singleton class by hand before going for any Java interview. This will develop your insight on coding mistakes made by Java programmers. On related note, In modern day of Test driven development, Singleton is regarded as anti pattern because of difficulty it present to mock its behaviour, so if you are TDD practitioner better avoid using Singleton pattern.





package main.java.com.code.interview.datastructures;





/* * A journey to write double checked locking of Singleton class in Java. */
class SingletonDCL {

private volatile static SingletonDCL _instance;



private SingletonDCL() {

// preventing Singleton object instantiation from outside


}
/*

* * 1st version: creates multiple instance if two thread access * this
* method simultaneously
*/

public static SingletonDCL getInstance() {

if (_instance == null) {

_instance = new SingletonDCL();


}
return _instance;
}

/*


* * 2nd version : this definitely thread-safe and only * creates one
* instance of Singleton on concurrent environment * but unnecessarily
* expensive due to cost of synchronization * at every call
*/
public static synchronized SingletonDCL getInstanceTS() {

if (_instance == null) {

_instance = new SingletonDCL();


}
return _instance;


}

/*
* * 3rd version : An implementation of double checked locking of Singleton.
* * Intention is to minimize cost of synchronization and improve
* performance, * by only locking critical section of code, the code which
* creates instance of Singleton class. * By the way this is still broken,
* if we don't make _instance volatile, as another thread can * see a half
* initialized instance of Singleton.
*/


public static SingletonDCL getInstanceDC() {

if (_instance == null) {

synchronized (SingletonDCL.class) {

if (_instance == null) {

_instance = new SingletonDCL();




}


}


}

return _instance;




}



public void testMe(){






System.out.println("Hey.... it is working!!!");







}





 

public static void main(String a[]){






SingletonDCL ms = getInstance();

ms.testMe();





SingletonDCL ts = getInstanceTS();

ts.testMe();





SingletonDCL dcl = getInstanceDC();

dcl.testMe();




}





}






No comments:

Post a Comment