Fundamentals 13 min read

Understanding Variable Visibility and the volatile Keyword in Java

The article explains Java’s variable‑visibility problem in multithreaded code, describes the Java Memory Model and the happens‑before rules, and shows how synchronization or declaring a field volatile (as in double‑checked‑locking Singleton) guarantees that updates become visible across threads and prevents instruction reordering.

Java Tech Enthusiast
Java Tech Enthusiast
Java Tech Enthusiast
Understanding Variable Visibility and the volatile Keyword in Java

This article explains the variable visibility problem in Java multithreading and how the volatile keyword and synchronization can solve it.

Example of the visibility issue:

public class VolatileDemo {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
        while (true) {
            if (myThread.isTag()) {
                System.out.println("----------");
            }
        }
    }
}

class MyThread extends Thread {
    private boolean tag;
    @Override
    public void run() {
        tag = true;
        System.out.println("子线程中tag为:" + tag);
    }
    public boolean isTag() { return tag; }
}

Because each thread works with its own copy of the variable, the main thread may never see the change made by the child thread.

The article then describes the Java Memory Model (JMM): shared variables are stored in main memory, each thread copies them to its own working memory, and without proper synchronization the copies are not kept consistent.

Solution using a synchronized block:

while (true) {
    synchronized (myThread) {
        if (myThread.isTag()) {
            System.out.println("----------");
        }
    }
}

Synchronization forces a memory barrier, making the updated value visible.

Preferred solution with volatile :

private volatile boolean tag;

When a variable is declared volatile , writes to it happen‑before any subsequent reads, guaranteeing visibility across threads and also preventing instruction reordering.

The article also covers the happens‑before principle, listing its six rules (program order, monitor lock, volatile, transitivity, start, join) and shows how they apply to the examples.

Application in the Singleton pattern:

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

Marking the instance field as volatile prevents other threads from seeing a partially constructed object.

Additional use‑cases such as a simple trigger mechanism and examples of instruction reordering are also discussed.

JavaConcurrencyMultithreadingvolatileJMM
Java Tech Enthusiast
Written by

Java Tech Enthusiast

Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!

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.