Fundamentals 5 min read

Understanding Double-Checked Locking Singleton Pattern in Java

This article explains the double-checked locking implementation of the Singleton pattern in Java, detailing why two null checks are necessary, the role of the volatile keyword in preventing instruction reordering and ensuring visibility across threads, and provides a complete example code.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Understanding Double-Checked Locking Singleton Pattern in Java

The article begins with a complete Java implementation of a thread‑safe Singleton using double‑checked locking, including the class definition, a volatile static instance field, a private constructor, and a synchronized block inside the getInstance method.

package cn.yqh.interview;

public class Singleton {
    private static volatile Singleton singleton = null;
    private Singleton() {}
    public static Singleton getInstance() {
        // first check
        if (singleton == null) {
            synchronized (Singleton.class) {
                // second check
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(new Runnable() {
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " : " + Singleton.getInstance().hashCode());
                }
            }).start();
        }
    }
}

The first null check (the "first verification") avoids entering the synchronized block once the instance has been created, improving performance by eliminating unnecessary lock contention.

The second null check (the "second verification") prevents multiple threads from creating separate instances when they concurrently pass the first check; without it, both threads could instantiate the Singleton, breaking the pattern.

The article also emphasizes that the volatile modifier on the instance field is essential. It stops the JVM from reordering the three steps of object creation (memory allocation, initialization, and reference assignment), which could otherwise allow another thread to see a partially constructed object.

Furthermore, volatile guarantees visibility: changes to the variable are always read from main memory, ensuring that all threads observe the most recent value.

In summary, both null checks and the volatile keyword are indispensable for a correct, thread‑safe Singleton implementation using double‑checked locking.

JavaConcurrencyvolatilesingletonDouble-Checked Locking
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.