Fundamentals 35 min read

Understanding JVM Memory Structure and the Java Memory Model (JMM): volatile, synchronized and Concurrency Basics

This article explains the differences between JVM memory layout and the Java Memory Model, clarifies how volatile and synchronized guarantee visibility, atomicity and ordering, and provides practical guidelines, code examples, and diagrams for mastering Java concurrency fundamentals.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Understanding JVM Memory Structure and the Java Memory Model (JMM): volatile, synchronized and Concurrency Basics

JVM Memory and JMM Memory Model

In interviews and concurrent programming you often encounter volatile and synchronized . This article summarises the core knowledge points and interview focus, using text and diagrams to improve your concurrency skills.

Key Questions

What is the difference between JMM and JVM memory structure?

What is the Java Memory Model (JMM) and how does it relate to concurrency?

What are the most important aspects of the memory model: instruction reordering, atomicity, memory visibility?

What does volatile visibility mean, its use cases and common pitfalls?

How does synchronized work internally and what is its relationship with the monitor?

JVM Memory Structure

Java source files are compiled to .class files, loaded by the JVM class loader, and executed either by the interpreter or the JIT compiler on the underlying OS. The JVM abstracts the hardware, enabling Java to run on Linux, Windows, macOS, etc.

Since Java 8 the permanent generation has been removed and replaced by Metaspace, so flags like -XX:PermSize and -XX:MaxPermSize are obsolete.

The JVM divides memory into several runtime data areas:

Heap : stores objects and arrays; the main area for garbage collection.

Java Virtual Machine Stack : per‑thread stack of stack frames that hold local variables, operand stacks, dynamic linking information and return addresses.

Method Area (Metaspace) : stores class metadata, constant pools, field and method data.

Native Method Stack : used for native (C/C++) method execution.

Program Counter (PC) Register : points to the next bytecode instruction for each thread.

public
int add() {
  int a = 1, b = 2;
  return a + b;
}

Each stack frame contains a local variable table, an operand stack, dynamic linking information and a return address.

Java Memory Model (JMM)

The JMM is a set of specifications that all JVM implementations must follow to guarantee consistent behavior of multithreaded programs across different hardware and compiler optimizations.

It addresses problems caused by CPU caches, instruction reordering, and compiler optimizations, ensuring that keywords such as volatile , synchronized and classes in java.util.concurrent work correctly.

The three most important concepts of JMM are:

Instruction Reordering

Atomicity

Memory Visibility

Instruction Reordering

Compilers, the JVM and CPUs may reorder instructions for performance, as long as single‑threaded semantics are preserved. In multithreaded code this can lead to unexpected results.

Reordering can reduce the number of loads and stores, improving speed, but it must not change the program order visible to a single thread.

Memory Visibility

When a thread writes to a volatile variable, the new value is immediately flushed to main memory, making it visible to other threads.

public
class Visibility {
    int x = 0;
    public void write() { x = 1; }
    public void read() { int y = x; }
}

If a thread updates x in its working memory but does not synchronize with main memory, another thread may still see the old value, causing a visibility problem.

Atomicity

Read/write of primitive types (except non‑volatile long and double ) are atomic. Compound actions like i++ are not atomic and require additional synchronization.

How JMM Solves These Problems

JMM defines two abstract memories:

Main Memory : shared by all threads.

Working Memory : a thread‑local copy of variables.

Eight atomic actions control the interaction between them:

read

load

store

write

use

assign

lock

unlock

These actions, together with memory barriers, guarantee the three JMM guarantees (reordering, atomicity, visibility).

volatile

volatile ensures that writes to a variable are immediately visible to other threads and prevents certain kinds of reordering.

Visibility : a write to a volatile variable happens‑before any subsequent read of that variable.

Prohibits Reordering : the compiler and CPU cannot reorder operations that cross a volatile read/write.

Correct Usage

Typical scenarios are boolean flags or single‑assignment fields where only simple reads/writes occur.

volatile
boolean shutdownRequested;

public void shutdown() { shutdownRequested = true; }
public void doWork() { while (!shutdownRequested) { /* do stuff */ } }

Another common case is the double‑checked locking singleton pattern, where volatile prevents the instance reference from being observed before the constructor finishes.

class
Singleton {
private
volatile
static
Singleton instance =
null
;
private
Singleton() {}
public
static
Singleton getInstance() {
if
(instance ==
null
) {
synchronized
(Singleton.
class
) {
if
(instance ==
null
)
                    instance =
new
Singleton();
            }
        }
return
instance;
    }
}

Incorrect Usage

volatile does **not** make compound operations atomic. For example, using it for a++ in multiple threads leads to lost updates.

public
class
DontVolatile
implements
Runnable {
volatile
int
a;
    public static
void
main(String[] args)
throws
InterruptedException {
        Runnable r =
new
DontVolatile();
        Thread t1 =
new
Thread(r);
        Thread t2 =
new
Thread(r);
        t1.start(); t2.start();
        t1.join(); t2.join();
        System.out.println(((DontVolatile) r).a);
    }
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) { a++; }
    }
}

The final value is usually less than 2000 because the increment is not atomic.

synchronized

synchronized provides mutual exclusion by acquiring a monitor (mutex) associated with an object. The monitor is implemented in the JVM using native OS mutexes.

When a thread enters a synchronized block, the JVM inserts the bytecode instructions monitorenter and monitorexit around the block.

Instance methods lock on this .

Static methods lock on the Class object.

Explicit synchronized blocks lock on the object specified in the parentheses.

Object Header and Lock States

Every Java object has a header consisting of a MarkWord and a Class Metadata pointer. The MarkWord stores hash code, GC age, and lock information. Depending on contention, the lock can be in one of four states:

No‑lock

Biased lock

Lightweight lock

Heavyweight lock

Lock escalation occurs as contention increases; the lock never downgrades.

The MarkWord changes its bits to reflect the current lock state (biased, lightweight, heavyweight, or unlocked).

Monitor Internals

ObjectMonitor maintains fields such as _owner (the owning thread), _WaitSet (threads waiting on wait() ), _EntryList (threads blocked trying to acquire the lock), _recursions (re‑entry count) and count (acquisition count).

Summary

The JVM memory structure is tied to the runtime data areas, while the Java Memory Model governs the semantics of concurrent Java programs. JMM abstracts away hardware‑level details, guaranteeing consistency, atomicity and ordering through memory barriers and eight atomic actions. volatile provides visibility and limited ordering guarantees, whereas synchronized offers full mutual exclusion, visibility, atomicity and ordering. Understanding these mechanisms is essential for writing correct and performant concurrent Java code.

Recommended Reading

Kafka Principles: Diagramming the Architecture

Architecture Design Methodology

Complete Kafka from an Interview Perspective

Database and Cache Write Consistency

JavaJVMconcurrencyvolatileMemory ModelJMMsynchronized
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.