What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
The classic double-checked singleton that uses an ordinary, non-volatile shared reference is broken under the Java Memory Model. Adding volatile changes the memory-ordering guarantees: the conventional corrected pattern can safely publish the reference while synchronized initialization prevents competing threads from creating it twice. It does not, however, make later changes to the singleton’s mutable state automatically thread-safe.
Is double-checked locking broken in Java?
It depends on which version you mean. The classic form with a plain shared reference is not safe: a thread can observe a non-null reference without the visibility and ordering guarantees needed to rely on the object’s construction. The JSR-133 reference describes double-checked locking as broken without explicit memory barriers or assumptions about the processor and compiler: The Java Memory Model.
The corrected form uses a volatile field. The Java Language Specification (Java SE 26, Chapter 17, §17.4.5) states: “A write to a volatile field happens-before every subsequent read of that field.” That ordering rule changes the argument; it is inaccurate to say Java has universally eliminated or forbidden the corrected idiom. Read the Java Language Specification, Chapter 17.
Why does the corrected code use both volatile and synchronized?
final class Service {
private static volatile Service instance;
static Service getInstance() {
Service result = instance; // first read
if (result == null) {
synchronized (Service.class) {
result = instance; // second read
if (result == null) {
result = new Service();
instance = result; // volatile publication
}
}
}
return result;
}
}
The first check avoids the monitor after initialization
When the first read finds an initialized instance, the method returns without entering the synchronized block. This is the fast path that gives double-checked locking its name.
The monitor serializes initialization
If the first read is null, the caller enters the monitor. Only one thread at a time can execute the initialization decision while holding that same monitor.
The second check handles a competing initializer
Another thread may have initialized the instance after this caller’s first read but before it acquired the monitor. The second read checks again while initialization is serialized. Without it, the waiting caller could construct and assign another instance.
Rank #2
The volatile field supplies the publication ordering
The assignment to instance is a volatile write; later reads of that same field receive the JLS happens-before guarantee. The JDK concurrency documentation explains that volatile reads and writes have memory-consistency effects similar to monitor entry and exit, but do not provide mutual-exclusion locking. In this pattern, the monitor and volatile field therefore have distinct roles. See the java.util.concurrent package documentation.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Describe this in terms of Java’s specified memory-model guarantees—not as volatile making construction atomic or performing a hardware cache flush. Implementations may optimize code, provided the resulting executions remain predictable under the JMM.
Why we need a volatile field with double-checked Singleton pattern
Without volatile, the synchronization inside the initialization block does not give an unsynchronized reader of the ordinary field the same publication guarantee. A caller on the fast path does not acquire that monitor, so it cannot rely on the monitor’s ordering effects. Declaring the shared field volatile gives those reads and the initialization write the required memory-consistency relationship under the JLS.
The key distinction is not that volatile replaces the lock. It does not ensure that only one initializer runs. The synchronized block does that; volatile makes publication visible and ordered for readers that do not enter the block.
Rank #4
What safe publication does not guarantee
Safe publication of the reference is not a blanket guarantee that all future concurrent operations on the object are safe. The JLS gives special initialization guarantees to correctly initialized final fields when construction completes before another thread can see the reference. Ordinary non-final fields do not receive the same guarantee merely because the reference was observed; the JLS describes executions in which a racy reader sees an initialized final field but a default value for a non-final field.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsDesign the singleton’s methods and mutable state separately. If multiple threads can update ordinary fields after publication, those accesses still need an appropriate synchronization strategy.
Best Value
When should you choose another singleton approach?
Double-checked locking is one option, not a universal default. Choose based on whether initialization must be lazy, whether construction needs parameters or can fail, and whether the design benefits from explicit synchronization. The JDK concurrency package documents higher-level synchronization facilities and their happens-before guarantees, but the cited sources do not establish a universal performance winner among singleton idioms. Avoid choosing on the basis of an unsupported benchmark claim.

