Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsNo: Java has not universally eliminated double-checked locking. The classic version that publishes a singleton through an ordinary, non-volatile shared field is broken. The commonly shown corrected version uses a volatile field and has a different memory-model justification. The distinction is visible in the code—and in the Java Language Specification’s happens-before rule.
What double-checked locking is trying to do
Double-checked locking aims to initialize a shared object only when first needed, while avoiding a monitor on calls made after initialization. The outer check handles the already-initialized case; the synchronized block protects the initialization path.
As an Amazon Associate I earn from qualifying purchases.
The title’s claim that Java “killed” the pattern is too broad. The Java Memory Model reference describes double-checked locking as broken without explicit memory barriers or assumptions about the processor and compiler. That warning applies to the classic ordinary-reference version, not automatically to the volatile-corrected form. The University of Maryland’s Java Memory Model page explains the historical issue.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Why the old, non-volatile version is broken
In the broken form, the shared field is an ordinary reference. A thread can see a non-null reference without the memory-ordering guarantee needed to ensure that it also sees the object’s constructor writes. The fact that construction appears as one statement in source code does not establish the required publication guarantee under the Java Memory Model.
The JSR-133 reference describes the pattern as broken without explicit memory barriers or assumptions about the processor and compiler. The key issue is not that every execution must fail; it is that the ordinary-reference version does not establish the guarantees the code relies on. The reference and its linked historical material discuss that limitation.
Why the corrected version uses both volatile and synchronized
A conventional corrected form declares the shared field volatile and keeps the second check inside the synchronized block:
Rank #2
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 two synchronization mechanisms have separate roles:
- The volatile field provides memory consistency. The Java Language Specification, Java SE 26, says: “A write to a
volatilefield happens-before every subsequent read of that field.” A thread that subsequently reads the published reference therefore participates in the specified ordering relationship. See JLS Chapter 17, §17.4.5. - The monitor serializes initialization attempts. Only one thread at a time can execute the guarded initialization block for
Service.class. The JDK concurrency documentation says volatile reads and writes have memory-consistency effects similar to monitor entry and exit, but “do not entail mutual exclusion locking.” See the Java SE 26 concurrency package documentation.
The second null check matters because another thread may initialize the instance after this thread’s first check but before it acquires the monitor. Once inside, the thread must check again before constructing another object.
These are Java memory-model guarantees, not a claim that volatile makes construction “atomic” or performs a hardware cache flush. The JLS defines the allowed ordering and visibility behavior; implementations may optimize so long as executions remain predictable under those rules. The specification describes those rules.
Why volatile is needed for this idiom
Without volatile, the fast-path read outside the synchronized block is not protected by that monitor. The volatile declaration supplies a defined happens-before edge between publication through the field and a subsequent read of that same field. The synchronized block alone cannot give an unsynchronized fast-path reader the same monitor-based guarantee.
Rank #4
Conversely, volatile alone does not serialize competing first-time initializers. The monitor prevents two threads that both observe null from simultaneously completing the guarded initialization. The idiom depends on both properties, not on volatile serving as a substitute for every form of synchronization.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Safe publication does not make later changes thread-safe
Correctly publishing the reference and its construction-time state is separate from making future operations on the object safe under concurrent use. A volatile reference does not automatically protect mutable fields or compound operations inside the object.
Best Value
The JLS gives special guarantees to correctly initialized final fields when construction completes before another thread sees the reference. It does not extend that same guarantee to ordinary non-final fields merely because the reference was observed. Its example permits a racy reader to see a final field’s initialized value while seeing the default value of a non-final field. See JLS §17.5 on final-field semantics. If a singleton’s state can change after construction, its methods and mutable data still need an appropriate concurrency design.
When to choose another initialization approach
Double-checked locking is one option, not a universal default. Choose based on whether initialization must be lazy, whether construction is parameterized or can fail, and whether the object’s later state is mutable. The JDK documents higher-level concurrency facilities and their memory-consistency guarantees, but the sources cited here do not establish a universal performance winner among singleton approaches. Avoid choosing on the basis of an assumed speed advantage without measurements for the actual application.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.




