All Articles
Listยท6 min read

6 Things Every Java Dev Should Know About the Memory Model

The Java Memory Model is why your multithreaded code works on your laptop and breaks in production. Six essentials that demystify it.

Part of: Advanced Java Development

The Java Memory Model (JMM) defines when one thread's writes become visible to another. Ignore it and you get bugs that vanish under a debugger and reappear only under load. Here are six things worth internalizing.

1. Threads Can Cache Variables

A thread may hold a copy of a field in a register or CPU cache. A write by one thread is not guaranteed to be seen by another unless the JMM says so. This is why a plain flag can loop forever:

boolean running = true; // another thread sets this false... while (running) { } // ...but this thread may never notice

2. volatile Guarantees Visibility

Marking the flag volatile forces reads and writes to go to main memory, so the change is seen immediately:

private volatile boolean running = true;

volatile fixes visibility. It does not make compound actions atomic.

3. volatile Is Not a Lock

count++ on a volatile int is still three operations โ€” read, add, write โ€” and two threads can interleave them and lose an update. For atomic compound actions use AtomicInteger or synchronized:

private final AtomicInteger count = new AtomicInteger(); count.incrementAndGet(); // atomic

4. happens-before Is the Real Rule

The JMM's core concept is happens-before: if action A happens-before B, A's effects are visible to B. Unlocking a monitor happens-before locking it; a volatile write happens-before a subsequent read of it; a thread's start() happens-before its run. These edges are what make concurrent code correct.

5. Final Fields Are Special

Correctly constructed final fields are guaranteed visible to other threads after construction, without synchronization. This is why immutable objects are inherently thread-safe โ€” there is nothing to see change.

6. Prefer Higher-Level Tools

You rarely need to reason about the JMM by hand. java.util.concurrent โ€” ConcurrentHashMap, BlockingQueue, AtomicReference, executors โ€” encodes the correct happens-before edges for you. Reach for those before hand-rolling synchronized blocks.

Summary

Multithreading bugs are usually visibility bugs: one thread cannot see another's writes. Remember that threads cache, volatile restores visibility (but not atomicity), happens-before is the underlying rule, and final plus immutability sidesteps the whole issue. When in doubt, let java.util.concurrent do the reasoning for you.

#Java#Concurrency#JMM#Threads

Want to go deeper?

Advanced Java Development

View Course