Five ways to implement Singleton pattern in Java

Tags: , , ,

In this post, I will describe five ways to implement the Singleton pattern in Java. They are Synchronization the getInstane() method,static final variable, using double checking lock with volatile keyword, using SingletonHolder, and Enum.

1. Classic Java Singleton pattern

The following code is the simplest implementation of Singleton Pattern in Java. However it is not multiple thread-safe. 

The singleton pattern implemented in the above example is easy to understand. We maintain a static reference to the singleton instance and returns that reference from the static getInstance() method. We also make the Constructor private, such that the client can only get the object of the Singleton class by calling the static getInstance() method. 

The above example also uses a technique known as lazy instantiation to create the singleton object. So the singleton instance is not created until the getInstance() method is called for the first time.

The advantage of the lazy instantiation is that it ensures the singleton instances are created only when needed. This is important for the system performance if it is very expensive to create the singleton instance. 

Why the above code is not thread-safe

The code in example 1 is not thread-safe because of the following code:

If a thread is preempted at Line 2 before the assignment is made, the instancemember variable will still be null, and another thread can subsequently enter the ifblock. In that case, two distinct singleton instances will be created. Unfortunately, that scenario rarely occurs and is therefore difficult to produce during testing. 

 

2 A thread-safe singleton pattern in java using Synchronization

We can synchronize thegetInstance() method to make the above code thread-safe:

The code in example 2 is thread-safe now, as only one thread can enter to the getInstance() method.

However, this method is not efficient, as we actually only need the method be synchronized the first time when it is called . Because synchronization is very expensive, synchronized methods can run up to 100 times slower than unsynchronized methods, we need to introduce a performance enhancement that only synchronize the singleton assignment in getInstance().

3.  Synchronize the critical code only

We might choose to rewrite thegetInstance() method by synchronizing the critical code only, like the following example:

 However, this method is not thread-safe. Consider the following scenario: Thread 1 enters the synchronized block, and, before it can assign the singleton member variable, the thread is preempted. Then another thread can enter the if block. The second thread will wait for the first thread to finish, but we will still wind up with two distinct singleton instances. Is there a way to fix this problem? 

4. Double-checked locking

Double-checked locking is a technique appears to make lazy instantiation thread-safe. That technique is illustrated in the following code:

Let’s reconsider the case that two threads enter the if code at the same tie. Imagine Thread 1 enters the synchronized block and is preempted. Subsequently, a second thread enters the if block. When Thread 1 exits the synchronized block, Thread 2 makes a second check to see if the singleton instance is still null. Since Thread 1 set thesingleton member variable, Thread 2’s second check will fail, and a second singleton will not be created. Or so it seems.

Unfortunately, double-checked locking is not guaranteed to work because the compiler is free to assign a value to the singleton member variable before the singleton’s constructor is called. If that happens, Thread 1 can be preempted after the singleton reference has been assigned, but before the singleton is initialized, so Thread 2 can return a reference to an uninitialized singleton instance.

Since double-checked locking is not guaranteed to work, we have to develop alternative methods 

5.Double-checked locking with volatile keyword

 The volatile prevents memory writes from being re-ordered, making it impossible for other threads to read uninitialized fields of your singleton through the singleton’s pointer.

However, we should avoid use the volatile based method, as it is hard to understand and it is easy to make mistakes. 

6. Thread-safe but not lay initialized 

This method is thread-safe, but it is not lazy initialized . The singleton object is created as soon as the class is loaded. 

7. The ultimate Thread-safe and efficient singleton pattern in Java 

The method is recommend by effective java.  It is lazy initialized, and multiple-thread safe. 

8. Using Enum

The best way to implement a thread safe Singleton Pattern in Java is using Enum. See the following example. 

 

Summary

In this post, I described 8 ways to implement java Singleton pattern. Actually, only 5 ways are correct: Synchronization the method, static final variable, using double checking lock with volatile keyword, using SingletonHolder, and Enum.  The last two methods should be used in practice. 

Reference:

http://javarevisited.blogspot.sg/2014/05/double-checked-locking-on-singleton-in-java.html

http://www.importnew.com/6461.html

http://stackoverflow.com/questions/11639746/what-is-the-point-of-making-the-singleton-instance-volatile-while-using-double-l