98. Java Memory Model & Happens-Before Guarantee
The Java Memory Model (JMM) defines how threads interact through shared memory; the happens-before relationship guarantees that memory writes by one thread are visibly observed by another without instruction reordering.
Java 21 (JLS Chapter 17)Explanation
Modern CPUs use multi-level hardware caches, store buffers, and out-of-order execution, while JIT compilers aggressively reorder instructions for performance. Without a formal specification, code running correctly on one architecture could read stale or half-initialized values on another. The Java Memory Model (JMM), codified in JLS §17.4, defines the exact rules under which a read of a variable is guaranteed to see a previous write.
The core concept is the happens-before order. If action A happens-before action B, then A's writes are visible to B and A is perceived to occur before B. Key happens-before rules in Java include: 1. Program order rule: Within a single thread, each action happens-before any subsequent action in program order. 2. Monitor lock rule: An unlock on a monitor lock happens-before every subsequent lock on that same monitor. 3. Volatile variable rule: A write to a volatile field happens-before every subsequent read of that same field. 4. Thread start rule: A call to Thread.start() happens-before any action in the started thread. 5. Thread termination rule: Any action in a thread happens-before any other thread successfully detects that thread has terminated (via join() or isAlive() == false). 6. Transitivity: If A happens-before B, and B happens-before C, then A happens-before C.
Without a happens-before link between a write and a read, the program contains a data race, and the JVM is permitted to observe stale data or out-of-order writes.
Example
public class HappensBeforeDemo {
private int data = 0;
private volatile boolean ready = false;
// Thread 1: Writer
public void writeData() {
data = 42; // 1. Normal write
ready = true; // 2. Volatile write (acts as a write-barrier)
// By JMM: 1 happens-before 2 (program order).
// Any subsequent read of 'ready' that sees true creates a happens-before link!
}
// Thread 2: Reader
public void readData() {
if (ready) { // 3. Volatile read (acts as a read-barrier)
// By JMM: 2 happens-before 3.
// Transitivity: 1 happens-before 2 happens-before 3 happens-before 4!
System.out.println("Data: " + data); // 4. Guaranteed to print 42, NEVER 0!
}
}
}Sources
- https://docs.oracle.com/javase/specs/jls/se21/html/jls-17.html#jls-17.4 — Java Language Specification: Java Memory Model
- https://shipilev.net/blog/2014/jmm-pragmatics/ — Aleksey Shipilëv: JMM Pragmatics