Fundamentals 7 min read

Why volatile and synchronized Can't Prevent Instruction Reordering in Java

An in‑depth analysis of Java’s instruction reordering versus ordered execution, illustrating how volatile ensures visibility but not atomicity, how synchronized guarantees atomicity and ordering yet cannot stop bytecode‑level reordering, with detailed DCL singleton bytecode walkthrough and multithreaded examples.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Why volatile and synchronized Can't Prevent Instruction Reordering in Java

Instruction Reordering vs Ordering

Problem Description

Instruction reordering and ordering are distinct. volatile guarantees visibility and prevents reordering of its own reads/writes but does not provide atomicity. synchronized guarantees atomicity, visibility, and ordering at the lock level, yet it does not forbid low‑level CPU or JVM reordering of individual instructions.

Note: “ordering” here does not mean that instruction reordering is prohibited.

DCL Bytecode Analysis

Object creation in Java is not atomic; it consists of three steps: memory allocation, constructor invocation, and reference assignment.

Double‑checked locking code

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;
    }
}

Relevant bytecode (excerpt) shows that new MySingleton() expands to four bytecode instructions (lines 17, 20, 21, 24). Line 17 allocates memory, line 21 invokes the constructor, and line 24 stores the reference into the static field.

The JVM may reorder these steps (e.g., 17‑24‑21) for performance.

Bytecode illustration
Bytecode illustration

Problems Caused by Reordering

Thread t1 may store the reference in INSTANCE before the constructor runs.

Thread t2 sees a non‑null INSTANCE, returns it, and uses an incompletely constructed object, leading to unpredictable behavior.

Reordering is harmless in a single‑threaded context but can produce subtle bugs in multithreaded scenarios.

Ordering Guarantees of synchronized

synchronized

does not prevent low‑level reordering; instead it provides a higher‑level ordering by converting concurrent method calls into serial execution under a monitor lock.

Code Example Demonstrating Serial Execution

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();
    }
}

Even if thread t2 obtains the reference before the constructor finishes, the synchronized test method forces the two threads to execute the print statement sequentially. By the time t2 acquires the lock, t1 has already completed object construction, so no error occurs.

Thus, synchronized guarantees serial execution of critical sections (ordering) but does not eliminate low‑level instruction reordering.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaconcurrencybytecodevolatileSingletonsynchronizedInstruction Reordering
Java Architect Essentials
Written by

Java Architect Essentials

Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.

0 followers
Reader feedback

How this landed with the community

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.