Safe publication and double-checked locking
What publishing an object means, how another thread can see a half-built object, the five safe publication idioms, and the whole singleton journey: synchronized, broken and fixed double-checked locking, the holder-class idiom and the enum singleton.
On this page
- Picture it first: the key before the house is finished
- What "publishing" an object actually means
- How a reader sees a half-built object
- Under the hood: the lazy-init race you can see every time
- The five ways to publish safely
- The singleton journey: Naive, Solid, Staff
- Real world
- Advanced: what the spec says, what the hardware does
- How to say it in the interview
📦 What is safe publication?
Publishing an object means making it reachable by another thread: storing its reference in a shared field, a collection, or handing it to a task. Safe publication means the other thread is guaranteed to see the object fully built, with every field the constructor wrote. Without it, Java allows a reader to get a perfectly valid reference to an object whose fields still look like 0 and null. Double-checked locking is the famous lazy-singleton trick that got this wrong for years.
For this lesson, we'll work out what "publishing" really means, how a reader can end up holding a half-built object, the five ways to publish safely, and then walk the whole singleton journey: the slow-but-correct version, the broken double-checked locking, the fixed one with volatile (and why a boring local variable makes it faster), the holder-class idiom and the enum singleton. Interviewers love this topic because almost everyone has written a singleton, very few can explain why the classic version is broken, and the follow-up "so how would you write it?" has a clear right answer with real trade-offs.
What you’ll learn
- Explain what publishing an object means and why
instance = new T()is really allocate, construct, store that another thread may see out of order - Say honestly why a half-built object is hard to reproduce on a laptop, and cite jcstress results that show it on x86 and AArch64
- List the five safe publication idioms: static initializer,
volatile/AtomicReference,finalfield, lock on both sides, concurrent collection - Tell immutable, effectively immutable and mutable objects apart and what each needs after publication
- Explain why classic double-checked locking is broken without
volatile, and why Java 5 (JSR-133) made thevolatileversion correct - Write volatile DCL with a local variable and explain the one-volatile-read saving
- Use the holder-class idiom (JLS 12.4.2 class-init lock) and the enum singleton, and know their trade-offs: no retry if init throws, no parameters
- Ask the staff-level question: does this even need to be lazy?
Premium lesson
Keep reading with the Java Pass
The rest of this lesson is part of Java One-Stop Interview Prep: in-depth explanations, diagrams, model answers and how to say them in the interview.
- Picture it first: the key before the house is finished
- What "publishing" an object actually means
- How a reader sees a half-built object
- Under the hood: the lazy-init race you can see every time
- The five ways to publish safely
- The singleton journey: Naive, Solid, Staff
- Real world
- Advanced: what the spec says, what the hardware does
- How to say it in the interview
From ₹299 · one-time payment · No auto-renewal
Further reading (13)
- JLS 21, Chapter 17.4 and 17.5: Memory Model and final Field Semantics: data races, happens-before, final-field freeze
- JLS 21, 12.4.2: Detailed Initialization Procedure: the class initialization lock behind the holder idiom
- The "Double-Checked Locking is Broken" Declaration (Pugh et al.): why DCL broke, and the JDK 5 volatile fix
- JSR-133 (Java Memory Model) FAQ, Manson and Goetz: what changed in Java 5, DCL section
- Aleksey Shipilev: Safe Publication and Safe Initialization in Java: jcstress failure counts on x86 and ARMv7; JMH costs of each singleton idiom
- Aleksey Shipilev: Java Memory Model Pragmatics
- jcstress sample BasicJMM_08_Finals: recorded partially constructed objects on x86_64 and AArch64
- java.util.concurrent package summary: Memory Consistency Properties: insert into a concurrent collection happens-before access
- Java Concurrency in Practice (Goetz et al., 2006), sections 3.5 and 16.2: safe publication idioms, effectively immutable objects, DCL
- Effective Java, 3rd edition (Bloch), Items 3 and 83: enum singleton; lazy initialization idioms and the local-variable DCL
- Kotlin stdlib LazyJVM.kt: SynchronizedLazyImpl: by lazy is volatile DCL with a local
- Guava Suppliers.java: MemoizingSupplier: DCL with a volatile flag; value piggy-backs on it
- JEP 502: Stable Values (Preview): JDK 25; followed by JEP 526 Lazy Constants in JDK 26