写入volatile变量为何会触发其他变量的刷新?
Great question—this is one of the most important (and easy to misinterpret) parts of Java's JSR-133 memory model. Let's break it down with practical, plain-language explanations:
The Core Guarantee: Happens-Before Relationships
The key here is the strict happens-before rule that applies to volatile variables. Here's what it boils down to:
When thread A writes to a volatile variable
f, every operation that happened before that write in thread A happens-before the write tof. And that write tofhappens-before any subsequent read offby another thread.
In simpler terms: Any changes thread A made to any variables (volatile or not) before writing the volatile variable must be visible to any thread that later reads the updated value of f. The volatile write acts as a "visibility checkpoint" that ensures all prior updates are synced to main memory.
How Memory Barriers Enforce This
Under the hood, volatile writes trigger memory barriers—low-level hardware instructions that block two problematic behaviors:
- Instruction Reordering: The compiler and CPU can't reorder operations that come before the volatile write to happen after it. For example, if thread A runs:
The write toint counter = 100; // Non-volatile variable volatile boolean updateDone = true;countercan never be moved after the write toupdateDone. - Cache Flush: All changes thread A has stored in its local CPU cache are flushed to main memory when the volatile write completes. No stale values get trapped in A's private cache.
When another thread reads the volatile variable updateDone and sees true, it also gets a memory barrier that forces it to reload all relevant variables from main memory (instead of relying on its own stale cache). That's why it sees the updated counter value.
A Concrete Example
Let's make this tangible with code:
// Thread A private int settings = 0; private volatile boolean settingsReady = false; public void loadSettings() { settings = 99; // Update non-volatile variable settingsReady = true; // Volatile write } // Thread B public void applySettings() { while (!settingsReady) { // Wait for settings to load } System.out.println(settings); // Guaranteed to print 99, not 0 }
Without the volatile modifier on settingsReady, Thread B might never see settings = 99 (it could read a stale cache value forever). But because settingsReady is volatile, the happens-before rule ensures that when B reads settingsReady = true, it must also see the updated settings value.
A Common Misconception to Clear Up
It's not that the volatile write actively triggers a flush of all other variables. Instead, the JMM's constraints force that all prior changes are visible once the volatile write is observed by another thread. The memory barriers just make sure the CPU and compiler don't break this guarantee.
内容的提问来源于stack exchange,提问作者Stephen

