Singleton Design Pattern Part Two

Singleton Design Pattern Part Two

In previous post Singleton Desin Pattern Part One

  • We have introduced the concept of singleton design pattern
  • we have talked about some version about them.
  • We achieved Lazy loaded Singleton Design
  • We Also designed a Singleton which was thread safe.

Lets Go deeper !!

Lazily Initialized Double-Checked Locking Singleton :

This pattern is explained in wiki Lazily Initialized Double-Checked Locking Singleton

public class DoubleCheckedLockingLazySingleton{
    private static volatile DoubleCheckedLockingLazySingleton instance;
    
    private DoubleCheckedLockingLazySingleton() {}
    
    public static DoubleCheckedLockingLazySingleton getInstance() {
        if(instance==null){
            synchronized (DoubleCheckedLockingLazySingleton.class) {
            
                // double check
                if(instance==null){
                    instance =new DoubleCheckedLockingLazySingleton();
                }
            }
        }
       return instance;
    }
}

In this version of lazy initialized singleton where instead of making the entire method synchronized, we create a synchronized block and wrap only the instantiation part inside synchronized block.

As we can see double instance==null is being performed hence it goes with the name. Second null checking is important here. Let's assume both T1 and T2 entered the getInstance() method and one of them entered the synchronized block and it sees that instance is null and hence creates the instance. If the null checking was not present then another instance would have been created.

Another very important aspect of above code block is the volatile keyword. And without volatile keyword this above code will not work!!

Why?

  • The basic principle is that compiler transformations (this includes the JIT, which is the optimizer that the JVM uses) can change the code around so that the code in the DoubleCheckedLockingLazySingleton constructor occurs after the write to the instance variable.
  • If it does this, then after the constructing thread writes to instance, but before it actually finishes constructing the object, another thread can come along and read instance before it is finished initializing.

See the double-checked locking is broken declaration for a much more detailed explanation.

So using volatile solves this problem.

Bill Pugh Singleton / Initialization-on-demand holder idiom: (lazy-loaded-singleton)

Bill Pugh came up with a very efficient solution to create singletons. It is called Initialization-on-demand holder idiom . In this approach, a static inner class is used to lazily create a singleton instance. In all versions of Java, the idiom enables

  • a safe
  • highly concurrent
  • lazy initialization of static fields with good performance.
public class LazySingleton {

    /** private constructor to prevent others from instantiating this class */
    private LazySingleton() {}

    /** This inner class is loaded only after getInstance() is called for the first time. */
    private static class LazyHolder {
        private static final LazySingleton INSTANCE = new LazySingleton();
    }

    public static LazySingleton getInstance() {
        return LazyHolder.INSTANCE;
    }
}

Notice:

  • The static class LazyHolder is only executed when the static method getInstance is invoked on the class LazySingleton and when it happens JVM will load and initialize the LazyHolder class.

  • The initialization of the LazyHolder class results in static variable INSTANCE being initialized by executing the (private) constructor for the outer class LazySingleton.

  • Since the class initialization phase is non-concurrent, no further synchronization is required in the static getInstance method during loading and initialization. And since the initialization phase writes the static variable INSTANCE in a sequential operation, all subsequent concurrent invocations of the getInstance will return the same correctly initialized INSTANCE without incurring any additional synchronization overhead.

In Simple word, the inner class is not loaded until the getInstance() method is invoked for the first time. This solution is thread-safe and doesn’t require any synchronization. It is the most efficient approach among all the singleton design pattern implementations.

Conclusion:

This concludes two part series of singleton design pattern.

Which Explains:

  • What is singleton design pattern.
  • Where it is being used.
  • When it should be used
  • Various Implementation of Singleton Design Pattern.

Thanks for reading. See you in the next post.

Avatar
Moshiour Rahman
Software Architect

My interests include enterprise software development, robotics, mobile computing and programmable matter.

comments powered by Disqus
Next

Related