Understanding Java Volatile Keyword and Memory Model
This article provides a comprehensive tutorial on Java's volatile keyword, covering its role in the Java Memory Model, the three concurrency fundamentals of atomicity, visibility, and ordering, and detailed explanations of volatile's visibility, ordering guarantees, implementation mechanisms, and a source code example.
Hello everyone, I am Chen Rui (Mike Chen), founder of Youzhi Academy. I will spend the next six months delivering a comprehensive architecture course with videos, notes, and assignments to help you get promoted and earn higher salaries.
This session focuses on five points:
1. Volatile keyword 2. Java Memory Model 3. Visibility in the Volatile memory model 4. How Volatile works 5. Volatile source code example
Before discussing Volatile, we review the three elements of the Java Memory Model: atomicity, visibility, and ordering, which are the core aspects of concurrent programming.
Three Fundamentals of Concurrent Programming
1. Atomicity
Similar to database transaction atomicity, an atomic operation cannot be interrupted; it either completes fully or fails completely. Simple reads and assignments (assigning a literal to a variable) are atomic, while compound operations like i++ involve multiple steps and are not atomic.
Because non‑atomic operations can lead to thread‑safety issues, synchronization (e.g., synchronized ) or atomic classes such as AtomicInteger and AtomicLong are required.
2. Visibility
When multiple threads share a variable, a change made by one thread must become immediately visible to the others.
3. Ordering
Compilers and processors may reorder instructions for performance, causing the execution order to differ from the source code order. Reordering does not affect single‑threaded programs but can break correctness in multithreaded scenarios.
Volatile
The volatile keyword in Java provides two guarantees for a shared variable:
Ensures visibility across threads.
Prevents instruction reordering, thus preserving ordering.
Note that volatile only guarantees visibility and ordering; it does not make compound actions (e.g., i++ ) atomic.
Volatile Memory Model
The Java Memory Model (JMM) is an abstract specification that defines how threads interact with main memory and their own working memory. All variables reside in main memory, while each thread has a private working memory that holds copies of the variables it uses.
Threads must read from and write to their working memory; they cannot directly access main memory or another thread's working memory. Data synchronization between working memory and main memory ensures consistency.
Main Memory : Stores Java objects and shared static data. Multiple threads accessing the same variable may encounter thread‑safety problems.
Working Memory : Each thread’s private copy of variables. It includes caches, write buffers, registers, and other optimizations. It is an abstract concept, not a physical memory region.
Implementation Principle of Volatile
Volatile guarantees memory visibility
The interaction between main memory and working memory follows eight atomic JMM operations: lock , unlock , read , load , use , assign , store , and write . The first four act on main memory, the latter four on working memory.
(1) lock : Exclusively locks a variable in main memory for a thread.
(2) unlock : Releases the lock, allowing other threads to access the variable.
(3) read : Copies the variable value from main memory to working memory.
(4) load : Stores the read value into the working‑memory copy.
(5) use : Passes the value to the thread’s execution engine.
(6) assign : Writes the engine‑processed value back to the working‑memory copy.
(7) store : Writes the working‑memory copy back to main memory.
(8) write : Commits the stored value to the shared variable in main memory.
Typical interaction sequence:
Copy variable from main memory to working memory ( read + load ).
Execute code and modify the shared variable ( use + assign ).
Flush working‑memory changes back to main memory ( store + write ).
Instruction Rules
read and load , as well as store and write , must appear as pairs.
After a variable is modified in working memory, an assign must be followed by a flush to main memory.
Only one thread can hold a lock on a variable at a time; the lock is re‑entrant, and the number of unlock calls must match the number of lock calls.
Locking a variable clears its value in the thread’s working memory, requiring a subsequent load or assign to re‑initialize it.
Before unlock , the variable must be synchronized back to main memory ( store / write ).
Volatile Source Code Example
For more content, visit https://mikechen.cc and continue learning.
Mike Chen's Internet Architecture
Over ten years of BAT architecture experience, shared generously!
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.