Home > Tutorials > Architecture

Thread safe singleton design pattern example

Last updated : October 1, 2022

The essential concept behind the singleton design pattern is to have no more than one instance of the target class at any given time per java virtual machine. That involves minor modifications to our regular java class that we intend to convert to a singleton class.

Is singleton thread safe?

A singleton class itself is not thread safe. Multiple threads can access the singleton same time and create multiple objects, violating the singleton concept. The singleton may also return a reference to a partially initialized object.

Implementation of the singleton class

When implementing a singleton class, we have to place certain restrictions on instantiating objects from our singleton class.

The caller must not be able to instantiate the object by calling the new operator. This direct instantiation is defeated by providing a private constructor, disallowing the use of new outside the class.

Here is a singleton class. But it is not thread-safe

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

To get the instance of the singleton class, we call the static method getInstance(). This method is made static since we should be able to call it without creating an object of our singleton class. When first calling this static method, an instance of the Singleton class is created, assigned to a private static Singleton instance, and returned. Every subsequent call to the method will return the same object. The Singleton instance variable is also static, allowing the static method getInstance() to access it.

Why is singleton not thread-safe?

If you analyze the above code carefully, you will notice some thread safety issues when multiple threads try to access our singleton. To prevent concurrent multi-threaded access, each thread must obtain a lock to access the getInstance() method.

The problems we face are:

  • Multiple threads can access the getInstance() method and create objects simultaneously, leading to multiple objects.
  • A thread may get a reference to a partially initialized object.

How to make a singleton thread-safe?

The short answer is a singleton can be made thread-safe by instantiating the singleton class inside a static inner class or static initializer block.

2 Ways to implement a thread-safe singleton class in java

  1. Using static inner class
  2. Using static initializer block

Using static inner class

If you are looking for a thread-safe singleton, the code below achieves it by implementing a static inner class. It does thread-safe lazy-initialization of the object without explicit synchronization. Note that the variable INSTANCE is wrapped in an inner class, utilizing the class loader to do synchronization. The class loader guarantees to complete all static initializations before it grants access to the class. This implementation lazy initializes the INSTANCE by calling LoadSingleton.INSTANCE when first accessed inside the getInstance() method.

public class Singleton {
private static class LoadSingleton {
      static final Singleton INSTANCE = new Singleton();
   }
   private Singleton() {}

   public static Singleton getInstance() {
      return LoadSingleton.INSTANCE;
   }
}

Using static initializer block

The below code illustrates how to implement a thread-safe singleton class in java using a static initializer block. The only difference is the way the instance is created. Static initializer block vs. static inner class.

public class Singleton { 
private final static Singleton instance; 
   static { 
	instance = new Singleton(); 
   } 
   private Singleton() {} 
   public static Singleton getInstance() { 
	return instance; 
   } 
}

When to use singleton class?

The concept of the Singleton pattern has always been a debatable topic. My in-depth research reveals very few acceptable reasons to use a singleton class. In most cases, the framework you use most likely has an out-of-the-box solution in place. Some examples are logging, cache, configuration, and database connection pools that provide a global point of access to that instance throughout the application.

L Raney
By: L Raney
Lance is a software engineer with over 15 years of experience in full-stack software development.
Read more...

Comments are disabled

No Comments