StampedLock Optimistic Reads — Interview Questions
Reviewed by Gurusankar M.
Short Answer
ReentrantReadWriteLock lets multiple readers proceed concurrently but still requires every reader to acquire and release an actual lock, which costs coordination even when writes are rare. StampedLock adds a third mode — optimistic read — where a reader takes a stamp, reads the data without blocking anyone, and then calls validate(stamp) to check whether a writer interleaved; if validation fails, it falls back to a real read lock and retries. For read-heavy, write-rare data, this avoids lock acquisition overhead entirely in the common case, at the cost of StampedLock being non-reentrant and considerably trickier to use correctly.
On this page
Concept Made Simple
Coffee Chat Question
“When would you reach for StampedLock's optimistic locking over ReentrantReadWriteLock?”
Remember It Faster
Mind Map Answer
Optimistic reads bet that nothing changes during the read and only pay the cost of verifying that bet, not the cost of preventing writes outright. It's the same philosophy as optimistic concurrency control in databases, applied to an in-memory lock.
- ReentrantReadWriteLock
- Readers always acquire a real (shared) lock
- StampedLock optimistic
- Read without locking, then validate(stamp) after
- Validation fails
- Fall back to a real readLock() and re-read
- Trade-off
- Not reentrant; easy to misuse; no Condition support
Key takeaway: StampedLock trades ReentrantReadWriteLock's simplicity for lower read-path overhead — only reach for it once profiling shows read-lock acquisition itself is the bottleneck on a hot, read-dominated path.
Learn by Doing
Hands-on Keyboard
class Point {
private double x, y;
private final StampedLock lock = new StampedLock();
double distanceFromOrigin() {
long stamp = lock.tryOptimisticRead(); // no blocking, no lock taken
double curX = x, curY = y; // read without synchronization
if (!lock.validate(stamp)) { // did a writer interleave?
stamp = lock.readLock(); // fall back to a real lock
try { curX = x; curY = y; }
finally { lock.unlockRead(stamp); }
}
return Math.sqrt(curX * curX + curY * curY);
}
void move(double dx, double dy) {
long stamp = lock.writeLock();
try { x += dx; y += dy; }
finally { lock.unlockWrite(stamp); }
}
}Think Beyond the Expected
What If?
Why is StampedLock non-reentrant, and what breaks if you call writeLock() twice on the same thread?
StampedLock trades reentrancy for a lighter-weight stamp-based implementation — calling writeLock() again from a thread that already holds it will deadlock, since the lock has no concept of 'the same thread already owns this.' This makes it unsuitable for code paths that might recursively re-enter the locked method, unlike ReentrantLock/ReentrantReadWriteLock which explicitly support that.
Real World
StampedLock earns its complexity in narrow, hot, read-dominated data structures — a coordinate/geometry cache, a frequently-read configuration snapshot — where profiling shows readLock() acquisition itself in the flame graph. Most application code never needs it; reaching for it by default over the simpler, reentrant, better-understood ReentrantReadWriteLock is a common over-engineering mistake.
Real Talk from Guru
I'd tell an interviewer: I don't start with StampedLock — I start with ReentrantReadWriteLock, or even just synchronized, and only move to optimistic reads when a profiler points at the read-lock acquisition itself as the cost. Its non-reentrancy has bitten teams that reached for it too early.
Interviewer's Expectation
Keywords they're listening for:
- Explains the stamp/validate() optimistic-read pattern
- Knows StampedLock is non-reentrant, unlike ReentrantLock
- Frames it as an optimization for measured read-heavy hot paths
- Knows optimistic reads must fall back to a real lock on validation failure
Common Mistakes
- Forgetting to validate() after an optimistic read
- Assuming StampedLock is reentrant like ReentrantLock
- Reaching for StampedLock without profiling data showing it's needed
Best Practices
- Default to ReentrantReadWriteLock; move to StampedLock only when profiling justifies it
- Always validate() after an optimistic read and fall back on failure
- Never call StampedLock methods recursively from the same thread
Follow-up Questions
- What happens if you forget to call validate() after an optimistic read?
- Why doesn't StampedLock support Condition objects?
- How does StampedLock's write lock differ from ReentrantReadWriteLock's?
Continue Learning with AI
Take this question deeper with your favourite AI assistant. Pick a depth, copy the prompt, or open it directly — AI is your learning companion, not a shortcut.
Plain-language foundations
I'm preparing for a software engineering interview and want to understand this from scratch, as a beginner. Topic: Locks (Multithreading) Interview question: "When would you reach for StampedLock's optimistic locking over ReentrantReadWriteLock?" Please: 1. Explain the core idea in simple, plain language, using an everyday analogy. 2. Define any technical terms you use. 3. Walk through one small, concrete example. 4. Finish with a single sentence I can easily remember. Keep the tone friendly and assume I'm new to this topic.
Was this answer helpful?
Affiliate links
Tools for Your Developer Workspace
Equipment for a comfortable, productive setup.
As an Amazon Associate I earn from qualifying purchases.
- MonitorView on Amazon : BenQ EW2790U 27-inch Monitor (opens in a new tab)
BenQ EW2790U 27-inch Monitor
- LaptopView on Amazon : Acer Aspire One Laptop (opens in a new tab)
Acer Aspire One Laptop
- Office ChairView on Amazon : Wakefit Gravita Ergonomic Office Chair (opens in a new tab)
Wakefit Gravita Ergonomic Office Chair