StampedLock: The High‑Performance Java 8 Lock That Outpaces ReentrantReadWriteLock
StampedLock, introduced in Java 8, provides three lock modes—including an optimistic read that uses a 64‑bit stamp—to achieve higher throughput than ReentrantReadWriteLock in read‑heavy workloads, and the article explains its internal state, usage patterns, code examples, and important limitations.
StampedLock, added in Java 8, is a high‑performance lock designed for scenarios with many reads and few writes. Its internal 64‑bit state variable is divided into three parts: the high 56 bits hold a version/sequence number that increments on every successful write‑lock acquisition, the 8th bit marks whether a write lock is held, and the low 7 bits count active read locks.
The optimistic‑read mode leverages this design: a thread obtains a stamp via tryOptimisticRead() without blocking, reads shared data, and then calls validate(stamp) to check whether the stamp changed, indicating a concurrent write. If validation fails, the thread falls back to a traditional read lock to guarantee consistency.
import java.util.concurrent.locks.StampedLock;
public class ConfigCenter {
private final StampedLock sl = new StampedLock();
private String config = "default_config";
private int version = 0;
// 1. Update configuration with an exclusive write lock
public void updateConfig(String newConfig) {
long stamp = sl.writeLock(); // may block until the write lock is acquired
try {
config = newConfig;
version++;
System.out.println(Thread.currentThread().getName() + " updated config to: " + config + ", version: " + version);
} finally {
sl.unlockWrite(stamp); // must release with the same stamp
}
}
// 2. Read configuration with a shared read lock (strong consistency)
public String getConfigWithReadLock() {
long stamp = sl.readLock(); // may block until the read lock is acquired
try {
return "V" + version + ":" + config;
} finally {
sl.unlockRead(stamp);
}
}
// 3. Optimistic read (best performance for read‑many/write‑few)
public String getConfigWithOptimisticRead() {
long stamp = sl.tryOptimisticRead(); // fast, never blocks
String currentConfig = config; // copy shared data to a local variable
int currentVersion = version;
// Validate the stamp; if it changed, a write occurred
if (!sl.validate(stamp)) {
// Fallback to a pessimistic read lock
stamp = sl.readLock(); // may block
try {
currentConfig = config;
currentVersion = version;
} finally {
sl.unlockRead(stamp);
}
}
return "V" + currentVersion + ":" + currentConfig;
}
// 4. Example of lock conversion: upgrade read lock to write lock when a condition matches
public boolean updateIfMatch(String expectedValue, String newValue) {
long stamp = sl.readLock(); // acquire read lock first
try {
while (config.equals(expectedValue)) { // check condition
long ws = sl.tryConvertToWriteLock(stamp); // attempt upgrade
if (ws != 0L) { // upgrade succeeded
stamp = ws; // use the new write‑lock stamp
config = newValue;
version++;
System.out.println("Condition update succeeded to: " + config);
return true;
} else {
// Upgrade failed (e.g., other readers still hold the lock); release read lock and retry
sl.unlockRead(stamp);
stamp = sl.writeLock(); // acquire write lock
// After acquiring the write lock, re‑check the condition (omitted here)
}
}
return false;
} finally {
sl.unlock(stamp); // generic unlock that determines the lock type automatically
}
}
}The article stresses the "read first, then validate" principle: validate(stamp) is the key step that determines whether a write occurred during the optimistic read. If validation fails, a downgrade to a traditional read lock is required. This pattern is ideal when read operations vastly outnumber writes and occasional retries are acceptable.
Important characteristics and limitations of StampedLock differ markedly from ReentrantReadWriteLock:
Non‑reentrant : the same thread cannot reacquire the lock without first releasing it, or it will deadlock.
No thread‑ownership concept : a lock acquired by one thread may be released or converted by another, demanding careful stamp management.
Condition objects not supported : unlike ReentrantLock, StampedLock cannot be used with Condition for complex coordination.
Stamp expiry : stamp values are recycled on a cycle of at least one year; unused stamps may become invalid after that period.
Key takeaways:
Optimistic reads combined with version‑stamp validation provide higher throughput than ReentrantReadWriteLock in read‑heavy workloads.
Prefer tryOptimisticRead() followed by validate(stamp) and fall back to a read lock when validation fails.
Always release the lock with the correct stamp inside a finally block to avoid deadlocks.
Remember the non‑reentrancy and lack of Condition support; avoid using StampedLock in scenarios requiring reentrancy or condition‑based waiting.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Senior Xiao Ying
Dedicated to sharing Java backend technical experience and original tutorials, offering career transition advice and resume editing. Recognized as a rising star in CSDN's Java backend community and ranked Top 3 in the 2022 New Star Program for Java backend.
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.
