Why Interviewers Keep Asking About Java’s volatile Keyword – Deep Dive into JMM

This article explains why the volatile keyword is a frequent interview topic, detailing its memory‑visibility and ordering guarantees, illustrating JMM concepts with examples, comparing it to synchronized, and showing how volatile interacts with atomicity and common concurrency patterns in Java.

Senior Brother's Insights
Senior Brother's Insights
Senior Brother's Insights
Why Interviewers Keep Asking About Java’s volatile Keyword – Deep Dive into JMM

Why Interviewers Love the volatile Keyword

In Java interviews, interviewers often start with the volatile keyword because it opens a path to discuss the Java Memory Model (JMM), low‑level JVM behavior, and concurrency concepts such as memory visibility, instruction reordering, and synchronization.

Key Characteristics of volatile

Ensures that writes to a volatile variable are immediately visible to other threads (memory visibility).

Prevents instruction reordering around the volatile read/write (ordering guarantee).

Memory Visibility Explained

The JMM defines a main memory and per‑thread working memories. When a thread writes to a volatile variable, the new value is flushed to main memory; when another thread reads the same variable, it must fetch the latest value from main memory.

Example scenario:

Thread A writes x = 1 (stores in its local cache)
Thread A flushes x to main memory → main memory now holds 1
Thread B reads x → fetches 1 from main memory

Thus, any thread sees the most recent write, which is not guaranteed for ordinary variables.

Other JMM Properties: Atomicity and Ordering

Besides visibility, the JMM also defines:

Atomicity : a single read or write of a variable is indivisible. Composite actions like i++ are not atomic.

Ordering : operations appear in program order within a single thread, but may be reordered across threads unless prevented by volatile or synchronization.

Instruction Reordering Example

class ReOrderDemo {
    int a = 0;
    boolean flag = false;

    public void write() {
        a = 1;          // 1
        flag = true;    // 2
    }

    public void read() {
        if (flag) {      // 3
            int i = a * a; // 4
        }
    }
}

Without volatile, the compiler or CPU may reorder the writes so that flag = true happens before a = 1. In a multithreaded scenario, another thread could see flag as true while still reading the old value of a, leading to unexpected results.

volatile Does Not Guarantee Atomicity

While each read/write of a volatile variable is atomic, compound operations are not. The following code demonstrates a race condition despite volatile:

public class Test {
    public volatile int inc = 0;
    public void increase() { inc++; }
    public static void main(String[] args) throws Exception {
        final Test test = new Test();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) test.increase();
            }).start();
        }
        while (Thread.activeCount() > 1) Thread.yield();
        System.out.println(test.inc);
    }
}

Two threads may both read the same value, increment it, and write back the same result, so the final count is often less than the expected 10 000.

When to Use synchronized, Lock, or Atomic Classes

To obtain atomicity for compound actions, you must use explicit synchronization mechanisms such as synchronized, Lock, or classes from java.util.concurrent.atomic.

volatile vs. synchronized

volatile

only affects variable visibility; synchronized also provides mutual exclusion. volatile can be applied only to fields; synchronized can be used on methods, blocks, and classes. volatile does not guarantee atomicity; synchronized does. volatile never blocks threads; synchronized may cause blocking.

Both ensure ordering, but synchronized also establishes a happens‑before relationship for all actions within the critical section.

Double‑Checked Locking Singleton Using volatile

class Singleton {
    private static volatile Singleton instance = null;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

The volatile modifier prevents the JVM from reordering the instance allocation and the assignment, ensuring that other threads never see a partially constructed object.

Conclusion

Understanding volatile provides insight into the JMM’s visibility and ordering guarantees, but for atomicity and complex synchronization you still need synchronized or higher‑level concurrency utilities. Treating interview questions as a way to explore deeper Java memory semantics can turn a single keyword into a broader knowledge network.

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.

JavavolatileJMMmemory visibility
Senior Brother's Insights
Written by

Senior Brother's Insights

A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.

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.