StampedLock分析
概述
StampedLock 是 Java 8 引入的一种高性能锁机制,位于 java.util.concurrent.locks
包中。它通过乐观读策略优化了读写场景,解决了传统 ReentrantReadWriteLock
的写线程饥饿问题,适用于读多写少的高并发场景。
核心特性
三种访问模式
写锁 (Write Lock)
独占锁,类似ReentrantReadWriteLock
的写锁。
获取锁:long stamp = lock.writeLock()
释放锁:lock.unlockWrite(stamp)
悲观读锁 (Read Lock)
共享锁,与其他读锁兼容,与写锁互斥。
获取锁:long stamp = lock.readLock()
释放锁:lock.unlockRead(stamp)
乐观读 (Optimistic Read)
无锁机制,仅通过戳记 (Stamp) 验证数据一致性:long stamp = lock.tryOptimisticRead(); // 获取戳记 // ... 执行读操作 ... if (!lock.validate(stamp)) { // 验证戳记有效性stamp = lock.readLock(); // 升级为悲观读锁// ... 重新读取数据 ...lock.unlockRead(stamp); }
性能优势
- 乐观读避免线程阻塞,提升读吞吐量
- 写锁优先:当写锁请求时,会阻塞后续读锁请求
- 支持锁的转换(如乐观读升级为悲观读)
局限性
- 不可重入:同一线程重复获取锁会导致死锁
- 不支持条件变量(Condition)
- 需手动管理戳记,编程复杂度较高
代码示例
import java.util.concurrent.locks.StampedLock;public class Counter {private int value;private final StampedLock lock = new StampedLock();// 写操作:使用写锁public void increment() {long stamp = lock.writeLock();try {value++;} finally {lock.unlockWrite(stamp);}}// 读操作:使用乐观读public int get() {long stamp = lock.tryOptimisticRead();int currentValue = value;if (!lock.validate(stamp)) {stamp = lock.readLock(); // 升级为悲观读锁try {currentValue = value;} finally {lock.unlockRead(stamp);}}return currentValue;}
}
适用场景
- 读操作频率远高于写操作(如缓存、计数器)
- 数据一致性要求允许短暂脏读
- 需要避免写线程饥饿的高并发系统
注意:使用时应严格遵循
try-finally
释放锁,避免因异常导致死锁。乐观读需配合validate()
验证,否则可能读取到过期数据。