StampedLock
ReentrantReadWriteLock 在大量读锁和少量写锁的情形下,容易造成写锁饥饿。
StampedLock 是 JDK 1.8 增加的实现,它不依赖 AQS,极大提高了读写锁的性能,但是它不支持“重入”,概念层面也比较难理解,还有一些顺序性相关的问题。因此设计上是希望在库里使用,而非业务代码中。
使用
StampedLock 有三种锁模式:
- 写锁
writeLock(),tryWriteLock()与tryWriteLock(long time, TimeUnit unit)- 这些方法都会返回一个 long 型变量,代表锁的当前版本和锁模式
- 读锁
readLock(),tryReadLock()与tryReadLock(long time, TimeUnit unit)
- 乐观读
tryOptimisticRead()与validate(long stamp)tryOptimisticRead乐观读取,已有写锁返回 0, 否则返回一个版本号validate用于检测版本号是否合法,如果上次读取后没有加过写锁则返回true- 该模式是
StampedLock与ReentrantReadWriteLock的主要区别
它还支持锁的升级和降级:tryConvertToWriteLock(long stamp)、
tryConvertToReadLock(long stamp) 和 tryConvertToOptimisticRead(long stamp)
细节
锁模式
StampedLock 使用了 long 型表示版本号(stamp)和锁状态,二者的编码模式有一定区别,对于 stamp,会计算 stamp & 0xFF,然后有如下状态:
1000_0000(WBIT)代表处于写锁模式0000_0000为 0 时代表处于乐观锁模式0111_1110(RFULL)代表持有读锁的线程数已满(126)- 其它情况也是读锁模式
而对于锁状态(state),也会先计算 state & 0xFF,再看状态:
0代表锁空闲0111_1111(RBITS) 是临时状态,代表读锁数量将要溢出