StampedLock (Java 8) is a non-reentrant lock with three modes — write, pessimistic read, and optimistic read — where each acquisition returns a long stamp used to release or validate. Its headline feature is the optimistic read: a lock-free read path that doesn't block writers and incurs no cache-line contention when there is no conflict.
How optimistic reading works
tryOptimisticRead() returns a stamp without acquiring anything — no CAS, no shared-state write. You copy the fields you need, then call validate(stamp). If no writer has acquired the lock since the stamp was issued, validate returns true and your snapshot is consistent. If a writer intervened, it returns false and you fall back to a real (pessimistic) read lock.
private final StampedLock sl = new StampedLock();
private double x, y;
double distanceFromOrigin() {
long stamp = sl.tryOptimisticRead(); // no lock taken
double cx = x, cy = y; // read into locals
if (!sl.validate(stamp)) { // a writer may have run
stamp = sl.readLock(); // fall back: pessimistic
try { cx = x; cy = y; }
finally { sl.unlockRead(stamp); }
}
return Math.sqrt(cx * cx + cy * cy);
}
void move(double dx, double dy) {
long stamp = sl.writeLock();
try { x += dx; y += dy; }
finally { sl.unlockWrite(stamp); } // release with the same stamp
}
Always read fields into locals before validating — validate only certifies the snapshot you already took.
Critical caveats
- Not reentrant. Re-acquiring in the same thread deadlocks. There is no hold count.
- Does not support
Condition. Noawait/signal. - Be careful with the JMM. Because the optimistic path doesn't establish a lock, the validate check is what guards visibility — don't act on the copied values until validation succeeds, and avoid dereferencing possibly-inconsistent references inside the optimistic block.
- Supports conversions:
tryConvertToWriteLocketc. allow upgrade attempts, whichReentrantReadWriteLockforbids.