Knowledge Guide
HomeConcurrencyConcurrency Foundations

The Java Memory Model — Visibility, volatile & happens-before

The bug: a flag you set is never seen

One thread flips running = false to stop a worker. The worker loops on while (running) — and never stops, even though the flag was clearly written. Nothing crashes; the program just hangs. This is a visibility bug, and it is the second pillar of concurrency after the race condition.

Why a write can be invisible

For speed, each CPU core keeps recently-used variables in its own registers and cache. A write by one thread may sit in that core's cache (or a register) and is not guaranteed to be flushed to main memory, nor is another thread guaranteed to re-read it. The compiler and CPU may also reorder instructions. Absent an explicit rule, one thread simply has no obligation to see another thread's writes.

Thread 1 writes running=false to main memory, but Thread 2 keeps reading a stale running=true from its own CPU cache and loops forever
Thread 1 writes running=false to main memory, but Thread 2 keeps reading a stale running=true from its own CPU cache and loops forever

Reproduce it

On a server JVM this commonly spins forever — the reader hoists running into a register:

class Worker implements Runnable {
    private boolean running = true;          // NOT volatile
    public void run() { while (running) { /* hot loop */ } }
    public void stop() { running = false; }  // another thread calls this
}
// main: start worker, sleep 100ms, worker.stop();  -> may never return

The fix: establish a happens-before edge

The Java Memory Model guarantees visibility only across a happens-before relationship. The cheapest one for a flag is volatile: a write to a volatile variable happens-before every later read of it, so the read must come from main memory.

private volatile boolean running = true;   // now stop() is always seen -> loop exits

The edges that create happens-before (the ones you actually use):

EdgeGuarantees
volatile write → later readthe read sees that write (and everything before it)
unlock → later lock (same monitor)everything before unlock is visible after lock
Thread.start()the new thread sees everything the starter did before start()
Thread.join()the joiner sees everything the joined thread did

The trap: visibility ≠ atomicity

volatile makes a single read or write visible — it does not make count++ atomic, because that is three operations (see Race Conditions). Rule of thumb:

volatile is for a flag or a single published reference. For a compound read-modify-write you need a lock or an atomic (next lesson).

Pitfalls

Takeaways


Re-authored for this guide; diagram hand-authored as SVG. Follows the Java Memory Model treatment in Java Concurrency in Practice (ch. 3) and Jenkov's concurrency tutorials. See also: Race Conditions, and Atomics & CAS.

🤖 Don't fully get this? Learn it with Claude

Stuck on The Java Memory Model — Visibility, volatile & happens-before? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **The Java Memory Model — Visibility, volatile & happens-before** (Concurrency) and want to truly understand it. Explain The Java Memory Model — Visibility, volatile & happens-before from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **The Java Memory Model — Visibility, volatile & happens-before** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **The Java Memory Model — Visibility, volatile & happens-before** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **The Java Memory Model — Visibility, volatile & happens-before** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes