Double-Checked Locking Pattern with Lazy Singletone Initialization

Keep calm and double check

In the real world of multicore processors, we have to write multi-threaded applications that would use all cores efficiently. This is very practical, when it comes to high-loaded servers (with a high amount of users trying to access service at the same time). For instance, after you have successfully introduced the new functionality on your web service or fixed some bugs, your first intuition would be to release the new version as soon as possible. At this point, when your users start to access your web service simultaneously, a situation may arise, when two or more users will initialize the same singleton or field value more than once. This is not a favorable type of scenario. It is also the main reason your applications should be ready to initialize its singletons (and not only) properly!

public final class Singleton {
    
    // block access for two threads simultaneous
    private volatile Singleton INSTANCE;
   
    /*
    * Blocks direct object creation
    */
    private Singleton() {
    }

    public Singleton getInstance() {

        // first check: two or more threads can pass this check
        if (INSTANCE == null) {
            synchronized (Singleton.class) {
                // second check: only one thread will initialize the variable instance
                if (INSTANCE == null) {
                    INSTANCE = new Singleton();
                }
            }
        }

        return INSTANCE;
    }
}

The code above does the singleton initialization in two major steps:

  1. The first step would be to check, if the singleton INSTANCE has been already initialized. No big deal.
  2. The second step is however very important. If the check for INSTANCE returns null and the singleton has not been initialized yet, in this case we first synchronize the thread access to get a unique access from only one thread. Afterwards we check the INSTANCE of the singleton class again. These actions are performed in order to be sure that no other thread has already modified the INSTANCE (between the first check INSTANCE for null value and synchronized block). Once a thread has received a unique access and checked INSTANCE for null, it initializes the singleton instance. Do not forget to declare the singleton instance as volatile.

Without the volatile variable, another thread could read a half-initialized INSTRANCE variable in the moment when the first thread is about to leave the synchronized block. The volatile variable guarantees happens-before behaviour. This means, that any write action related to the variable will take place prior to any reads. As a result, in the memory the object will be created only once, while your code will be possible to use safely in a multithreaded environment.

However, starting Java 1.5 release, Enum class was introduced. It does allow for an easy multithread-safe creation of a singleton instance.

public enum Singleton {
    INSTANCE;
}

Many programmers prefer Enums to handcrafting singletons by themselves. Personally I also share this approach and thus I don’t recommend using anything but Enum singletons in your multithreaded applications. This will reduce side-effects, errors and obvious memory leaks in your programs.

The Double Checked pattern itself does allow you to initialize any preferred variable in a multithreaded environment, not just a singleton class. Many interviewers tend to ask this question in the job interviews (especially if you are a junior in the beginning of your Software Development career) in order check your ability to understand the basics of multithreaded programming.

Contents