StampedLock was added for advanced cases where read-mostly access patterns may benefit from something lighter than ordinary read-lock coordination.
Its defining feature is optimistic read.
That means a thread can:
- read without taking a conventional read lock first
- then validate whether a conflicting write happened
This can reduce coordination overhead in the right workload, but it also makes the API easier to misuse.
Problem Statement
Imagine a routing structure that is read constantly by request threads and updated only occasionally by a refresh thread.
A normal exclusive lock may serialize too much.
A ReentrantReadWriteLock allows readers to overlap, but every reader still has to acquire a read lock.
If reads are extremely frequent and writes are rare, even that read-lock coordination may become noticeable.
That is the niche StampedLock is trying to address.
Modes
StampedLock exposes three major modes:
- optimistic read
- read lock
- write lock
The API returns a numeric stamp token that must later be:
- validated
- or used to unlock the specific acquired mode
This is more powerful than ordinary lock APIs, but also more error-prone.
Why This Change Was Added
Traditional read-write locks still coordinate readers through explicit read-lock acquisition.
In very read-heavy scenarios, that can still add measurable overhead.
StampedLock offers an optimistic path:
- read fields quickly
- validate whether a write interfered
- retry with a stronger lock if needed
That can help when:
- reads dominate heavily
- write interference is rare
- profiling shows reader coordination overhead matters
This is not a general-purpose replacement. It is a specialized optimization tool.
Runnable Example
import java.util.concurrent.locks.StampedLock;
public class StampedLockDemo {
public static void main(String[] args) {
Point point = new Point();
point.move(10, 20);
System.out.println("Distance = " + point.distanceFromOrigin());
}
static final class Point {
private final StampedLock lock = new StampedLock();
private double x;
private double y;
void move(double deltaX, double deltaY) {
long stamp = lock.writeLock();
try {
x += deltaX;
y += deltaY;
} finally {
lock.unlockWrite(stamp);
}
}
double distanceFromOrigin() {
long stamp = lock.tryOptimisticRead();
double currentX = x;
double currentY = y;
if (!lock.validate(stamp)) {
stamp = lock.readLock();
try {
currentX = x;
currentY = y;
} finally {
lock.unlockRead(stamp);
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
}
}
The optimistic-read path is:
- take a stamp
- read fields
- validate the stamp
- fall back to a read lock if validation fails
If you skip the validation step, the whole design becomes incorrect.
Production-Style Scenario
Potential fits:
- hot read-mostly geometry, routing, or statistics structures
- workloads with many reads and rare writes
- code where profiling shows read-lock overhead matters
Example:
- request threads repeatedly compute derived values from a mostly stable in-memory snapshot
- a background refresher writes only occasionally
In that shape of workload, optimistic reads can avoid some reader coordination cost.
When It Helps
StampedLock is most promising when:
- reads dominate heavily
- the read path is hot
- writes are rare and short
- you can tolerate the extra implementation complexity
- the team understands the validation model
Without those conditions, the gains often do not justify the added risk.
When It Hurts
Poor fits:
- general business code where simplicity matters more
- teams unfamiliar with the API
- write-heavy workloads
- codebases where maintainability is a bigger concern than squeezing out some read-side overhead
Because the API is more manual, it is easier to write code that is technically wrong while still looking plausible.
Common Mistakes
- forgetting to validate optimistic reads
- reading fields optimistically and then acting on them without fallback
- using the wrong unlock method for the acquired mode
- choosing
StampedLockbefore proving a real read-heavy need
The API gives more control, but it also removes some of the safety rails developers are used to.
Comparison with Other Options
Compared with ReentrantReadWriteLock:
StampedLockmay reduce read-side coordination overhead- but it is harder to use correctly
Compared with immutable snapshot replacement:
StampedLockkeeps one mutable structure- immutable replacement may still be simpler in many backend systems
The fastest-looking primitive is not always the best system design.
Key Takeaways
StampedLockadds optimistic read alongside ordinary read and write modes.- It exists for advanced read-heavy cases where traditional read locking may still cost too much.
- Correctness depends on validating optimistic reads and falling back when needed.
- Use it selectively, with measurement and discipline, not as a blanket upgrade.
Next post: When StampedLock Helps and When It Hurts
Comments