Happens-Before Relationship
TL;DR
- The Happens-Before Relationship is the foundational rule of the Java Memory Model.
- If Action A happens-before Action B, then the memory changes made by Action A are guaranteed to be visible to Action B.
- It is a mathematical guarantee provided by the JVM that prevents stale data reads and unsafe instruction reordering.
Concept
“Happens-before” does not strictly mean “occurs earlier in real-time.” It is a contractual guarantee about memory visibility.
If Thread 1 updates x = 5 at 12:00:00, and Thread 2 reads x at 12:00:01, Thread 2 might still see x = 0 if there is no happens-before relationship connecting them (because the value 5 is stuck in Thread 1’s CPU cache).
The JMM defines specific scenarios that establish a happens-before relationship. The most common ones are:
- Program Order Rule: Within a single thread, every action happens-before every subsequent action.
- Monitor Lock Rule: An unlock on a
synchronizedmonitor happens-before every subsequent lock on that same monitor. - Volatile Variable Rule: A write to a
volatilevariable happens-before every subsequent read of that same variable. - Thread Start/Join Rule: A call to
Thread.start()happens-before any action in the started thread. Any action in a thread happens-before any other thread successfully returns fromThread.join()on it.
Examples
public class HappensBeforeDemo {
private volatile boolean flag = false;
private int data = 0;
// Thread 1 executes this
public void write() {
data = 42; // Action A
flag = true; // Action B (volatile write)
}
// Thread 2 executes this
public void read() {
if (flag) { // Action C (volatile read)
// If we get here, C read the 'true' written by B.
// By JMM rules: B happens-before C.
// By Program Order: A happens-before B, and C happens-before D.
// Therefore, A happens-before D!
// Thread 2 is absolutely guaranteed to print 42, not 0.
System.out.println(data); // Action D
}
}
}
Interview Questions
Q: Is the “Happens-Before” relationship transitive?
A: Yes! Transitivity is a core property. If A happens-before B, and B happens-before C, then the JVM guarantees that A happens-before C. This is exactly how the volatile flag in the example above guarantees the visibility of the non-volatile data variable.
Q: If Thread A writes to a variable at 1:00 PM, and Thread B reads it at 1:05 PM, is that a happens-before relationship?
A: No. Time is completely irrelevant to the Java Memory Model. If there is no synchronization mechanism (like a lock, a volatile variable, or a thread join) connecting Thread A and Thread B, there is no happens-before relationship. Thread B could theoretically read stale data for hours or days. You must explicitly establish the relationship using Java concurrency constructs.