Mastering Java Memory Model: Unlocking Thread Visibility and Concurrency
This article explains Java's concurrency fundamentals, covering shared memory vs. message‑passing models, the abstract structure of the Java Memory Model, instruction reordering, write‑buffer effects, memory barriers, and the happens‑before rules that guarantee correct thread communication.
1. Key Issues in Concurrency Programming Models
Concurrency programming uses two main models: the shared‑memory model and the message‑passing model, each needing to solve two critical problems—communication between threads and synchronization.
Shared‑memory model: Threads communicate implicitly by reading and writing shared variables in memory; synchronization must be explicitly specified by the programmer.
Message‑passing model: Threads communicate explicitly by sending messages; synchronization is implicit because a message must be received before it can be processed.
2. Abstract Structure of the Java Memory Model (JMM)
In Java, all instance fields, static fields, and array elements reside in heap memory, which is shared among threads, making them subject to the memory model.
JMM determines when a write to a shared variable by one thread becomes visible to another thread. It defines an abstract relationship between each thread’s local memory (a copy of shared variables) and the main memory.
JMM abstract model: Shared variables exist in main memory; each thread has a local memory that stores a copy of those variables.
JMM thread‑communication process: Thread A flushes its updated variables from local memory to main memory; Thread B reads those updates from main memory into its local memory, completing communication. This process always passes through main memory, providing the visibility guarantees.
3. Instruction Reordering from Source Code to CPU
Compilers and processors reorder instructions to improve performance. The following diagram illustrates the typical reordering steps.
4. Processor Effects on Memory Operations
Modern processors use a write buffer, which temporarily stores data that a thread writes to memory. This reduces stalls caused by memory latency and allows batch flushing, merging multiple writes to the same address, thus improving bus utilization and overall efficiency.
Impact on execution order: The processor may perform reads and writes in an order different from the program’s logical order, potentially leading to inconsistent results.
To address this, Java compilers insert memory‑barrier instructions at appropriate points to prevent certain types of processor reordering that would affect program correctness. JMM defines four kinds of memory barriers (shown below).
5. Happens‑Before Principle
In JMM, if the result of one operation must be visible to another, the two operations must satisfy the happens‑before relationship.
Program order rule: Within a single thread, actions earlier in the program happen before later actions.
Monitor lock rule: Unlocking a monitor happens before any subsequent locking of that same monitor.
Volatile variable rule: A write to a volatile variable happens before any subsequent read of that variable.
Thread start rule: Calling Thread.start() happens before any action in the started thread.
Thread termination rule: All actions in a thread happen before another thread detects its termination (e.g., via Thread.join()).
Thread interruption rule: Calling interrupt() happens before the interrupted thread detects the interruption.
Object finalization rule: Completion of an object’s constructor happens before its finalize() method starts.
Transitivity: If A happens before B and B happens before C, then A happens before C.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
