Singleton Pattern with Thread-safe and Reflection-safe

October 31, 2019

What is a Singleton Pattern

Following constraints are applied:

  • Where we can restrict the number of instances of a class to just 1
  • No-one should be able to create another instance of the class
  • Should provide a way to get the instance of the method
  • Should be thread safe

Some add-on requirements

  • Should not degrade performance
  • Should also not work if someone instantiate using reflection (Very important actually)

Naive Singleton solution

Some basics around singleton implementation:

  • Need to make constructor as private, so that no-one from outside can call it
  • Need to provide a static method which will return the instance
  • Need to declare a static variable inside class of same type

Lets look at some naive solutions:

class Singleton {
      private static Singleton singleton = new Singleton();

      private Singleton() {}

      public static Singleton getInstance() {
            return singleton;
      }
}

Do you see any issue with above code?


Well, you are instantiating the class on load time itself. If during the lifetime of your code, nobody wants this instance. This instance will be kept in memory unused.

Lazy Initialization

Lets lazy-initialize it

class Singleton {
      private static Singleton singleton = null;

      private Singleton() {}

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

Do you see any issue with above code?


Assume you are working in multi-threaded environment. And, there might be a possibility that more than one thread call getInstance() method at the same time. So, all of them are going to see the instance variable as null. And, each one of them will be calling the constructor, and each will receive a new copy. This is the issue of thread safe.

Solving Thread Safety

class Singleton {
      private static Singleton singleton = null;

      private Singleton() {}

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

The most naive thread-safe solution is to make whole getInstance() method as synchronized. Synchronized keyword makes a method thread safe, but with extra overhead. Note: it will take a lock on complete class (static method) unnecessary, which is a costly operation. Whereas, we just need to protect the code where we are checking the instance with null.

Lets optimize it.

Optimized Thread Safe solution

class Singleton {
      private static Singleton singleton = null;

      private Singleton() {}

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

Above approach is called as Double Lock. For the very first time, when it is not instantiated. Threads might come at first check (instance == null), all of them will proceed. But, there comes the lock now. So, only one thread can enter the protected block. And, again we are checking for null. And, instantiating only when it is not initialized. After this thread exists the protected block. Other thread will enter. Now, it will not see this as null, so it will not instantiate it. The benefit we are getting from this is for further calls, we will never take lock after the instance is initialized.


Do you see any issue with above code?


Well, when the program is loaded into memory. OS and JVM performs bunch of optimizations. And, it allocates separate memory to each thread in the stack. There might be a possibility (for very small duration of time) that when one thread instantiates the class, it still remains in its private memory (stack). And, then another thread again instantiates (even after double lock, because it still sees it as null).

There is special keyword in java: volatile, which applies to declaration of variables.

It is an instruction to compiler that *Do not make any optimization to this thing, and make only one copy of this in memory, so that it will always reflect fresh state*

Use of Volatile

Now, take a look at the code.

class Singleton {
      private static volatile Singleton singleton = null;

      private Singleton() {}

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

The singleton class looks OK? Right?

Lets take a look at some advanced optimization. If you have used concept of *reflection* of java, you can still call its constructor. Basically you can access even private things of a class using reflection. So, all constaints goes for a toss?

Lets fix this.

Avoid instantiation via Reflection

class Singleton {
      private static volatile Singleton singleton = null;

      private Singleton() {
            if (instance != null) {
                  throw new RuntimeException("Use only getInstance() to get instance!");
            }
      }

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

Note the constructor definition now.

Pitfalls of Singleton Pattern

Lets look at some pitfalls of this pattern.

  • This pattern is often overused. This pattern is so simple and popular that people tend to use it where it is not required.
  • There are some performance issues associated with singleton pattern. If you wrongly use them.
  • Since there are private constructors and private instance variable. They are difficult to unittest.
  • Its very easy to make it thread-unsafe. If you are not careful, this mistake is very often.
  • People often get confused this with factory pattern.

Similar Posts

Latest Posts