Java Memory Model (JMM)

The Java Memory Model (JMM) defines how threads interact with memory in Java. It specifies how variables are stored in memory and how threads access and modify those variables in a multi-threaded environment.


Why Java Memory Model is Needed

Modern CPUs use caching and reordering optimizations. Without a memory model, different threads might see inconsistent data. JMM ensures predictable behavior in concurrent programs.

JMM defines rules for visibility, ordering, and atomicity of shared variables.

Main Components of JMM

  • Main Memory
  • Thread Working Memory

Main Memory

Stores all shared variables. Every thread reads and writes shared data from main memory.

Thread Working Memory

Each thread has its own local working memory where it keeps copies of variables from main memory.

Threads do not interact directly with main memory. They work with their local copies.

Example of Visibility Problem


class SharedData {

    boolean flag = false;

    void writer(){
        flag = true;
    }

    void reader(){
        while(!flag){
            // may loop forever
        }
        System.out.println("Flag changed");
    }

}
Problem: The reader thread may never see the updated value of flag due to caching.

Solution Using volatile


class SharedData {

    volatile boolean flag = false;

    void writer(){
        flag = true;
    }

    void reader(){
        while(!flag){
        }
        System.out.println("Flag changed");
    }

}
The volatile keyword ensures visibility of changes across threads.

Key Concepts in Java Memory Model

1. Visibility

When one thread updates a variable, other threads should see the updated value.

2. Atomicity

An operation that executes completely or not at all.

Example:


AtomicInteger counter = new AtomicInteger();

counter.incrementAndGet();

3. Ordering

JVM and CPU may reorder instructions for performance. JMM defines rules to maintain correct execution order.


Happens-Before Relationship

Happens-before guarantees that memory writes by one thread are visible to another thread.

Examples:

  • Thread start()
  • Thread join()
  • Volatile variable write/read
  • Lock and unlock operations
If A happens-before B, then all changes made by A are visible to B.

Real World Example

Consider a microservice updating configuration settings shared across threads. Without proper synchronization, some threads may see outdated values.

Solution:

  • Use volatile variables
  • Use synchronized blocks
  • Use concurrent collections

Quick Summary

  • JMM defines how threads access shared memory
  • Ensures visibility, ordering, and atomicity
  • Threads use local working memory
  • volatile ensures visibility
  • synchronized ensures visibility and ordering
  • Happens-before rule guarantees memory consistency

0 comments

Leave a comment