Singleton Design Pattern and Thread Safety in Java
Singleton Design Pattern
Singleton design pattern is one of the simplest design pattern which ensures that only one object of a class can be created and it provides a global point of access to that instance.
It comes under creational design pattern as it provides one of the best ways to create an object.
This is useful when we need to have only one instance of our class for example a single DB connection shared by multiple objects as creating a separate DB connection for every object may be costly. Similarly, there can be a single configuration manager or error manager in an application that handles all problems instead of creating multiple managers.
Definition
Singleton pattern is a design pattern that restricts the instantiation of class to one object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class Singleton { private static Singleton instance; // private constructor to restrict the instantiation of Singleton Class private Singleton() { } //GetInstance method to provide global access to Singleton instance public static Singleton getInstance() { if (instance==null) instance = new Singleton(); return instance; } } |
In the above code, we have provided a private constructor of the class to restrict the creation of the Singleton instance from outside. To create the instance of the singleton class, one can only call getInstance() method which is a static method. Since static methods can be called using class names, so we can call as Singleton.getInstance()
; and get the object of Singleton class.
So singleton design pattern also promotes lazy initialization of instances, that means the instance of Singleton class will be created only when getInstance()
method is called.
Thread Safe Singleton Pattern
When multiple threads executed getInstance method of Singleton class (as in first way of singleton design pattern) it ends up creating multiple instance of Singleton class, this breaks the rule of Singleton design.
To ensure thread safety we can create Singleton in these ways:
1. Eager Initialization
By creating instance on calling getInstance method, the singleton instance is lazily initialized. Eager or early initialization of Singleton class instance can be done as below:
1 2 3 4 5 6 7 8 9 10 11 12 |
class Singleton { // static initializer for Singleton Class instance private static Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } } |
The above code does instance creation of Singleton object in static initializer. JVM executes static initializer when the class is loaded and hence this is guaranteed to be thread safe. Use this method only when your singleton class is light and is used throughout the execution of your program.
2. Synchronizing getInstance method
One way to make getInstanceMethod
thread safe we can synchronize the getInstance method which makes sure that only one thread at a time can execute getInstance().
The main disadvantage of this is method is that using synchronized every time while creating the singleton object is expensive and may decrease the performance of your program. However if performance of getInstance() is not critical for your application this method provides a clean and simple solution.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Singleton { private static Singleton instance; private Singleton() {} // Only one thread can execute the getInsance at a time public static synchronized Singleton getInstance() { if (instance==null) instance = new Singleton(); return instance; } } |
3. Double checked Locking
Best way to achieve thread safe Singleton pattern
If we see carefully only once an object is created, so synchronization is no longer useful because now instance
will not be null and any sequence of operations will lead to consistent results.
So we will only acquire lock on the getInstance() once, when the instance
is null. This way we only synchronize where its actually needed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// Double Checked Locking based implementation of // singleton design pattern class Singleton { private volatile static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { // To make thread safe synchronized (Singleton.class) { // check again as multiple threads // can reach above step if (instance==null) instance = new Singleton(); } } return instance; } } |
We have declared the instance
as volatile which means when the thread tries to access the instance field it reads the correct value from the main memory and not from the thread cache. This method drastically reduces the overhead of calling the synchronized method every time.
Refer issues with Singleton pattern
Happy Learning!!