How to Create Thread Safe Singleton in Java: Simple Guide
To create a thread safe singleton in Java, use the
double-checked locking pattern with a volatile instance variable or use a static inner helper class that holds the singleton instance. Both ensure only one instance is created safely when multiple threads access it.Syntax
The thread safe singleton uses a private static volatile instance variable, a private constructor, and a public static method to get the instance. The method checks if the instance is null before and after synchronizing to avoid unnecessary locking.
- volatile: ensures visibility of changes across threads.
- synchronized block: prevents multiple threads from creating multiple instances.
- private constructor: prevents external instantiation.
java
public class Singleton { private static volatile Singleton instance; private Singleton() { // private constructor } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
Example
This example demonstrates a thread safe singleton using the double-checked locking pattern. Multiple threads calling getInstance() will get the same instance without creating duplicates.
java
public class Singleton { private static volatile Singleton instance; private Singleton() { System.out.println("Singleton instance created"); } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } public void showMessage() { System.out.println("Hello from Singleton!"); } public static void main(String[] args) { Runnable task = () -> { Singleton singleton = Singleton.getInstance(); singleton.showMessage(); }; Thread thread1 = new Thread(task); Thread thread2 = new Thread(task); thread1.start(); thread2.start(); } }
Output
Singleton instance created
Hello from Singleton!
Hello from Singleton!
Common Pitfalls
Common mistakes include:
- Not using
volatilefor the instance variable, which can cause threads to see a partially constructed object. - Synchronizing the entire
getInstance()method, which hurts performance. - Creating multiple instances in multithreaded environments without proper locking.
Using the static inner helper class is a simpler alternative that avoids these pitfalls.
java
public class WrongSingleton { private static WrongSingleton instance; private WrongSingleton() {} // Wrong: no synchronization or volatile public static WrongSingleton getInstance() { if (instance == null) { instance = new WrongSingleton(); } return instance; } } // Correct approach using static inner class public class CorrectSingleton { private CorrectSingleton() {} private static class Holder { private static final CorrectSingleton INSTANCE = new CorrectSingleton(); } public static CorrectSingleton getInstance() { return Holder.INSTANCE; } }
Quick Reference
Summary tips for thread safe singleton in Java:
- Use
volatilewith double-checked locking for lazy initialization. - Prefer static inner helper class for simpler and efficient thread safety.
- Keep constructor private to prevent external instantiation.
- Avoid synchronizing entire
getInstance()method to improve performance.
Key Takeaways
Use volatile and double-checked locking to create a thread safe singleton with lazy initialization.
Static inner helper class is a simpler and efficient way to ensure thread safety.
Always keep the constructor private to prevent creating multiple instances.
Avoid synchronizing the whole method to reduce performance overhead.
Not using volatile can cause subtle bugs with partially constructed instances.