Singleton Class in Java

The double-checked locking pattern is a technique used to lazily initialize an object while ensuring thread safety. In Java, it’s commonly used for implementing the Singleton design pattern. However, it’s important to note that double-checked locking is not recommended in Java because of potential issues with memory visibility and race conditions. Instead, it’s recommended to use other approaches like static initialization or Enum Singletons, which provide better thread safety guarantees.

Nevertheless, here’s how you can implement the double-checked locking pattern for a Singleton class in Java:


public class Singleton {
    private static volatile Singleton instance; // volatile ensures visibility of changes across threads

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) { // First check without synchronization
            synchronized (Singleton.class) {
                if (instance == null) { // Second check with synchronization
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

Explanation:

  • The volatile keyword ensures that changes made to the instance variable are visible to all threads. Without volatile, there’s a risk of a partially initialized instance being seen by other threads, leading to unexpected behavior.
  • The getInstance() method first checks if the instance variable is null without synchronization. If it’s null, it proceeds to acquire a lock on the class object (using synchronized) to prevent multiple threads from creating separate instances concurrently.
  • Inside the synchronized block, a second check is performed to ensure that only one thread initializes the instance. This is necessary because multiple threads could have passed the first null check and acquired the lock, and only one of them should proceed to create the instance.
  • If the instance is still null inside the synchronized block, a new instance of the Singleton class is created. Subsequent calls to getInstance() return the already initialized instance.

While the double-checked locking pattern appears straightforward, it’s prone to subtle issues related to memory visibility and instruction reordering, especially in older versions of Java. As a result, it’s generally recommended to avoid using this pattern and instead opt for safer alternatives like static initialization or Enum Singletons, which provide better thread safety guarantees without the need for explicit synchronization.

Leave a comment

Your email address will not be published. Required fields are marked *