The Java Memory Model (JMM) is the part of the language specification (JSR-133, since Java 5) that defines when and how writes made by one thread become visible to other threads, and which instruction reorderings are legal. It solves the problem that, without rules, the compiler, JIT, and CPU are free to cache and reorder memory operations in ways that make multithreaded behavior undefined.
Why a memory model is needed at all
A single-threaded program runs as if in program order — that's the "as-if-serial" rule. But the JVM, the JIT, and the hardware aggressively optimize: values are held in registers, writes sit in store buffers, loads are speculated, and independent instructions are reordered. None of this is observable within one thread. Across threads, it absolutely is. Without a defined model, a write you make is not guaranteed to ever reach another thread's read.
class Flawed {
boolean ready = false; // not volatile
int value = 0;
void writer() { value = 42; ready = true; }
void reader() {
while (!ready) { } // may loop forever — never sees ready=true
System.out.println(value); // may print 0 — reorder of the two writes
}
}
Two things can go wrong here, and the JMM explains both. The reader may never observe ready becoming true (a visibility failure — the JIT can hoist the read out of the loop). And even if it does, it might read value as 0, because the writer's two independent stores can be reordered.
What the JMM actually provides
The JMM is defined around the happens-before relation. It does not promise "no reordering"; it promises that if there is a happens-before edge between two actions, the first's effects are visible to and ordered before the second. You create those edges with synchronized, volatile, final, Thread.start/join, and the java.util.concurrent machinery (which is built on them).
Marking ready volatile fixes the example: the volatile write happens-before the volatile read, and transitively the value = 42 write becomes visible too.