Why ReentrantLock Guarantees Memory Visibility: JMM, Happens‑Before, and Memory Barriers
This article explains how Java's ReentrantLock guarantees memory visibility for shared variables without using volatile, by leveraging the Java Memory Model's happens‑before guarantees, the lock's internal volatile state, and underlying CPU memory‑barrier instructions such as the LOCK prefix.
The author, a backend engineer working on hotel pricing cache, noticed that a simple ReentrantLock test increments a shared variable count correctly even though count is not declared volatile . This raises the question: how is the updated value made immediately visible to other threads?
To answer this, the article introduces several key concepts:
Java Memory Model (JMM) : defines the semantics of how threads interact through memory, including the ordering of reads and writes to shared variables.
Memory ordering : early CPUs followed program order, but modern processors may reorder instructions unless synchronization constructs (e.g., synchronized , volatile , CAS) are used.
Happens‑before : a set of ordering rules that guarantee visibility. For example, an unlock on a monitor happens‑before every subsequent lock on the same monitor.
Although volatile is the most familiar way to obtain visibility, the article shows that the same effect is achieved by ReentrantLock because its implementation relies on a volatile field and the JMM's happens‑before guarantees.
Key code fragment of a ReentrantLock‑protected increment:
private static ReentrantLock LOCK = new ReentrantLock();
private static int count = 0;
// thread code
LOCK.lock();
try {
count++;
} finally {
LOCK.unlock();
}When a thread releases the lock, the JMM defines that the unlock happens‑before the next lock acquisition, ensuring that all writes performed inside the critical section (including the increment of count ) become visible to the next thread.
The internal implementation of ReentrantLock (simplified) is also shown:
private volatile int state; // key volatile variable
protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = getState(); // read volatile state
// ... lock acquisition logic ...
}
protected final boolean tryRelease(int releases) {
// ... release logic ...
setState(c); // write volatile state (publish writes)
return free;
}Thus each lock acquisition performs three actions: read the volatile state, execute the critical section (e.g., count++ ), and write the volatile state on release, which publishes all prior writes.
At the hardware level, the volatile write is implemented using the x86 LOCK prefix, a memory‑barrier instruction that forces the CPU to flush pending writes to memory and ensures cache coherence across cores. This barrier provides the same visibility guarantees as a volatile write.
Consequently, the visibility of count after a ReentrantLock‑protected increment is achieved through the chain:
Lock/unlock establishes a happens‑before relationship.
The lock’s internal volatile state enforces a memory barrier (STORE‑LOAD) via the LOCK prefix.
The CPU’s cache‑coherency mechanism propagates the updated value to other cores.
The article also notes that non‑fair ReentrantLock adds an extra CAS step, which on x86 also uses the LOCK prefix and therefore provides the same memory‑barrier effect.
Summary : ReentrantLock ensures memory visibility without explicit volatile by relying on the JMM’s happens‑before rule, an internal volatile field, and the CPU’s LOCK‑prefix memory barrier that forces cache flushes and maintains coherence.
References:
http://gee.cs.oswego.edu/dl/jmm/cookbook.html
https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.html (Chapter 8)
https://www.ibm.com/developerworks/library/j-jtp03304/index.html
https://stackoverflow.com/questions/2972389/why-is-compareandswap-instruction-considered-expensive
http://ifeve.com/java-memory-model-5/
https://en.wikipedia.org/wiki/Memory_barrier
https://en.wikipedia.org/wiki/Java_memory_model
Qunar Tech Salon
Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.
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.