Under The Hood
backend java JSR-133 (JMM), JDK 21+

Java Memory Model (JMM): volatile, Memory Barriers & Happens-Before

Last updated
Prerequisites:
Java threads and synchronized basics
Understanding of CPU caches and memory visibility
  • java
  • jmm
  • volatile
  • happens-before
  • memory-model
  • concurrency
  • memory-barriers

Read at your depth

The practical view

The Java Memory Model defines when one thread is guaranteed to see another thread's writes. The key rule: happens-before. If action A happens-before action B, then A's effects are visible to B. Rules that create happens-before: a volatile write happens-before a subsequent volatile read of the same variable; unlock happens-before a subsequent lock of the same monitor; thread.start() happens-before any action in the started thread; thread.join() happens-before everything after it; writing through a thread-safe queue (BlockingQueue) establishes happens-before. volatile gives visibility but not atomicity (use AtomicInteger or synchronized for compound ops).

The same idea in other frameworks

react equivalent
N/A — JVM concurrency concern.

Legacy vs modern

Broken visibility with plain fields vs volatile flag

A plain boolean flag read by another thread has no visibility guarantee (may loop forever); volatile publishes the write via happens-before.

before → after
Plain boolean stop flag (no visibility)
static boolean stop = false; // ❌ OLD: not volatile — worker may never see the write
volatile flag with happens-before
static volatile boolean stop = false; // ✅ NEW: write → read creates happens-before

Interview gotchas

Context

This tests the core JMM semantics — interviewers want the visibility-vs-atomicity distinction and the precise meaning of the happens-before edge, not just 'volatile is for flags'.

The mechanical answer

Happens-before is a partial order on actions: if action A happens-before action B, then A's writes are visible to B, and B observes A's ordering. It is NOT a statement about wall-clock time — it's a visibility/ordering contract that lets you reason about concurrent code. volatile creates happens-before between a write and a subsequent read of that variable; synchronized creates it between unlock and subsequent lock; thread start/join and thread-safe queue operations create it too. But volatile does not provide atomicity: count++ is read-modify-write, and two threads doing it concurrently can both read the same value and lose an increment. For atomic compound operations you need synchronized, atomic classes (AtomicInteger using CAS), or locks — which create their own happens-before edges on top of atomicity.

Trap

The naive answer is 'volatile makes the variable thread-safe'. It guarantees visibility/ordering, not atomicity — volatile count++ is still racy. Another trap: thinking happens-before is transitive only within one synchronization chain — it is transitive, which is how the model composes (A→B and B→C implies A→C). Candidates who separate visibility from atomicity show real JMM understanding.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.