Java Memory Model, volatile & happens-before — Java Interview Guide | Cracked Java
Senior

Java Memory Model, volatile & happens-before

The contract that makes concurrent code correct: visibility vs atomicity vs ordering, volatile, the happens-before relation, final-field semantics, and why double-checked locking needs volatile.

Prereqs: synchronization

The Java Memory Model (JMM), specified by JSR-133 in Java 5, is the contract between the programmer, the compiler, and the hardware that defines exactly when a write by one thread becomes visible to a read by another. Without it, the optimizations every layer is allowed to make — reordering instructions, caching values in registers, store buffers — would make multithreaded behavior unpredictable. The JMM does not eliminate reordering; it tells you which reorderings you are guaranteed to not observe, and gives you the tools (volatile, locks, final) to establish those guarantees where you need them.

The three problems it solves

Concurrency bugs come from three distinct phenomena, and a senior engineer keeps them separate. Visibility: a thread may never see another thread's write, because the value sits in a CPU cache or a register the JIT chose. Ordering: the compiler and CPU may reorder independent instructions, so the order a thread appears to execute in differs from program order as seen by another thread. Atomicity: a compound action like i++ is three operations (read, modify, write) that can interleave. The JMM addresses visibility and ordering directly; atomicity of compound actions still requires locks or atomic classes.

happens-before is the whole game

The JMM is defined in terms of one relation: happens-before. If action A happens-before action B, then A's memory effects are visible to and ordered before B. It is the only guarantee you can rely on; everything else is fair game for reordering.

volatile and final

volatile gives a field visibility and ordering (the happens-before edge above), but not atomicity for compound updates. final fields get a special guarantee: if an object is correctly constructed (no this escape), any thread that sees a reference to it is guaranteed to see its final fields fully initialized — the basis for safe publication of immutable objects. This module covers each of these, plus why double-checked locking is broken without volatile.

Questions

7 in this topic