Java › Concurrency & Threads
How does the Java Memory Model's happens-before relationship formally define when changes made by one thread are guaranteed to be visible to another thread, and what role does the volatile keyword play?
AdvancedAnswer
The Java Memory Model (JMM) defines a happens-before partial ordering of operations across threads: without an established happens-before relationship between a write in one thread and a subsequent read in another, the JMM makes no guarantee the reading thread will ever observe the write (due to CPU caching, instruction reordering by the compiler/JIT/CPU, or memory visibility effects) -- volatile establishes a happens-before relationship for reads/writes of that specific field (a write to a volatile field happens-before any subsequent read of that same field by another thread), and additionally prevents certain compiler/CPU reorderings around it, but notably does NOT make compound operations (like increment) atomic, only guaranteeing visibility and ordering, not mutual exclusion.
public class FlagExample {
private volatile boolean running = true; // volatile ensures visibility across threads
public void stop() {
running = false; // write is guaranteed visible to other threads reading 'running'
}
public void doWork() {
while (running) { // without volatile, this loop might NEVER see the update, looping forever
// work
}
}
}Real-world example A background worker thread's while (running) loop fails to terminate when a separate control thread sets running = false, traced to the running field not being marked volatile, meaning the JVM/CPU was legally permitted to cache the field's value in the worker thread and never observe the other thread's write, resolved by adding the volatile modifier.