Backend Development 6 min read

Instruction Reordering and Ordering in Java: Analysis of Double-Checked Locking

The article explains the distinction between instruction reordering and ordering in Java, analyzes how volatile and synchronized affect memory visibility and atomicity, and demonstrates with bytecode and multithreaded examples why double‑checked locking requires both volatile and synchronized to avoid partially constructed singleton instances.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Instruction Reordering and Ordering in Java: Analysis of Double-Checked Locking

First, the article clarifies that instruction reordering and ordering are different concepts; volatile guarantees visibility and prevents reordering but not atomicity, while synchronized guarantees atomicity, visibility, and ordering, though it does not forbid instruction reordering.

It then breaks down the three steps of object creation ( Object obj = new Object(); ) and presents the classic double‑checked locking (DCL) singleton code, followed by a bytecode illustration showing how the new MySingleton(); statement expands into separate allocation, constructor call, and reference assignment instructions that can be reordered by the JVM.

The reordering problem is described: if thread T1 assigns the instance reference before the constructor finishes, thread T2 may see a non‑null instance and use an incompletely initialized object, leading to subtle bugs in multithreaded environments.

Since synchronized does not prevent such reordering, the article shows a test where two threads obtain the singleton and invoke a synchronized test method. The synchronized block serializes the execution, ensuring that by the time the second thread acquires the lock, the singleton has already been fully constructed, thus avoiding the reordering issue.

In conclusion, synchronized provides ordering by turning concurrent execution into serial execution, but it cannot alone guarantee that internal instruction reordering does not produce partially constructed objects; therefore, both volatile and synchronized are needed for safe DCL.

public class MySingleton { private static MySingleton INSTANCE; private MySingleton() {} public static MySingleton getInstance() { if (INSTANCE == null) { synchronized (MySingleton.class) { if (INSTANCE == null) { INSTANCE = new MySingleton(); } } } return INSTANCE; } public static void test(final MySingleton singleton) { synchronized (MySingleton.class) { System.out.println(singleton); } } }

public class MySingletonTest { public static void main(final String[] args) { new Thread(() -> { MySingleton instance = MySingleton.getInstance(); MySingleton.test(instance); }, "t1").start(); new Thread(() -> { MySingleton instance = MySingleton.getInstance(); MySingleton.test(instance); }, "t2").start(); } }

Javaconcurrencyvolatilesynchronizedinstruction reorderingDouble-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.