The Java Memory Model and the Happens-Before Relation
JSR 133 rebuilt Java's thread semantics around a formal memory model in which happens-before relationships explain when writes must become visible across threads.
Java’s promise of portability eventually had to include multiprocessor memory behavior
Java was designed to run across machines with different processors and virtual machines, but multithreaded code creates a deeper portability problem than bytecode alone. Different CPUs permit different reorderings, and just-in-time compilers perform transformations that can change when writes become visible to another thread. A language that says only what a single thread computes leaves too much ambiguity for shared-memory programs. Java therefore needed a formal memory model describing which concurrent executions are legal.
A portable thread API is not enough without visibility rules
Two virtual machines can implement the same Thread methods yet disagree about shared-memory results unless the language also defines how reads, writes, locks, and volatile variables interact.
The original Java memory model proved too weak and too restrictive in the wrong places
By the early 2000s, researchers had identified flaws in the original specification, including difficulties surrounding volatile fields, final fields, compiler optimizations, and causality. JSR 133 was created specifically to revise the Java Memory Model and thread specification. The Java Community Process describes the work as defining the semantics of threads, locks, volatile variables, and data races.[1] The goal was not merely to document existing JVM behavior but to produce rules programmers and implementers could both rely on.
JSR 133 became final as part of the Java 5 generation
The JSR reached final release in September 2004 and was incorporated into the Java Language Specification and J2SE 5.0.[2] The expert group included researchers and industry participants who had been studying weak memory for both hardware and programming languages. The revision gave Java one of the most influential language-level memory models of the multicore era and established terminology that later programmers encountered through the Java concurrency libraries.
The specification had to serve both programmers and virtual-machine implementers
If the rules were too weak, programmers could not reason about code; if they were too strong, JVMs could not optimize efficiently across diverse processors.
Happens-before became the central relation for ordinary reasoning
Chapter 17 of the Java Language Specification defines program order, synchronization order, synchronizes-with edges, and their transitive closure, the happens-before relation.[3] If action A happens-before action B, then the effects required by the model flow from A to B. Monitor unlock and later lock operations, volatile writes and later reads, thread start, and thread termination followed by successful join can create these relationships. Correctly synchronized code can therefore reason about visibility without describing cache protocols or machine instructions.
Data races separate well-disciplined Java programs from surprising executions
A program has a data race when conflicting accesses to the same variable occur without the required happens-before ordering and at least one access is a write. JSR 133 was designed so correctly synchronized programs receive strong, intuitive semantics, while programs with races can exhibit reorderings that surprise programmers. The formal paper by Jeremy Manson, William Pugh, and Sarita Adve explains the new model and the challenge of defining causality while still permitting compiler and processor optimizations.[4]
Synchronization is a visibility contract as well as a mutual-exclusion mechanism
Entering and leaving a monitor does more than decide who owns a lock. It establishes ordering edges that determine which earlier writes another thread is guaranteed to observe.
Volatile changed from a weak feature into a defined synchronization primitive
Under the revised model, a write to a volatile field happens-before subsequent reads of that field, giving volatile a clear cross-thread visibility role. This lets Java express state flags and publication patterns without using a full monitor in every case. Doug Lea’s JSR-133 cookbook translated the model into compiler terms, discussing reorderings, barriers, and the implementation obligations associated with volatile and locks.[5] The document also shows why a language memory model reaches deep into compiler back ends and processor-specific code generation.
Final fields received special guarantees for safe initialization
JSR 133 also strengthened the semantics of final fields so that properly constructed objects can safely expose final-field values without ordinary synchronization under specified conditions.[1] This was important for immutable objects and security-sensitive classes. The design recognized that object construction is a recurring publication pattern and that programmers needed stronger guarantees than the old model provided.
The model made object construction part of concurrency semantics
Visibility is not only about explicit locks. The language can attach ordering guarantees to lifecycle events such as construction, thread start, and thread completion.
Why the Java Memory Model belongs in the history of concurrency
The Java Memory Model matters because it moved concurrency semantics into the programming language itself. JSR 133 repaired defects that could not be solved by library documentation, the Language Specification formalized happens-before, and the compiler community translated those rules into barriers and reorder constraints for real hardware.[2][3][5]
The model also influenced how programmers discuss modern shared-memory correctness. Terms such as safe publication, data race, volatile visibility, and happens-before became practical engineering vocabulary rather than research-only concepts.
Most importantly, the JMM acknowledges that source order, compiler order, and processor order are different layers. Correct concurrent programming requires a contract connecting them. JSR 133 made that contract explicit enough that one Java program could retain defined meaning across aggressively optimizing JVMs and heterogeneous multiprocessor machines.
Works Cited
- 01
- 02
- 03
- 04
- 05Doug Lea — The JSR-133 Cookbook for Compiler Writers gee.cs.oswego.edu
CodeHistory is a living archive. Citations document the evidence used for this edition; later evidence may refine the account.
Submit a research lead