The Double-Checked Locking Singleton is a design pattern in Java used to efficiently and thread-safely initialize a singleton object, avoiding unnecessary synchronization once the instance is initialized.
Let’s break it down 🧠
☝️ What’s a Singleton?
A singleton is a class where only one instance is ever created.
🚨 Problem: Naive Singleton is not Thread-Safe
public class Singleton {
private static Singleton instance;
public static Singleton getInstance() {
if (instance == null) { // ❌ two threads can get here at the same time!
instance = new Singleton();
}
return instance;
}
}
✅ Solution: Double-Checked Locking
It means:
- Check if
instance
isnull
→ if so, - Lock and check again,
- Create the instance.
🔐 Thread-Safe + Efficient Version:
public class Singleton {
private static volatile Singleton instance;
private Singleton() {} // private constructor
public static Singleton getInstance() {
if (instance == null) { // First check (no locking)
synchronized (Singleton.class) {
if (instance == null) { // Second check (with locking)
instance = new Singleton();
}
}
}
return instance;
}
}
💡 Why volatile
?
Without volatile
, the JVM might reorder instructions and return a reference to a partially constructed object.
// Under the hood, new Singleton() could be:
1. allocate memory
2. assign reference to `instance`
3. run constructor ← ⚠ might not finish before another thread sees it!
With volatile
, you ensure visibility and no reordering.
✅ Summary
Feature | Benefit |
---|---|
Double-checked if (instance == null) | Avoids locking after initialization |
synchronized inside block | Makes initialization thread-safe |
volatile | Prevents instruction reordering + ensures visibility |
Thread-safe? | ✅ Yes |
Performance efficient? | ✅ Yes (after initialization, no locking) |