什么是 Java 的 StampedLock?
什么是 Java 的 StampedLock?
回答重点
StampedLock 是 Java 8 引入的一个锁机制,与传统的 ReentrantLock 和 ReadWriteLock 相比,StampedLock 通过引入乐观读锁和时间戳(stamp)的概念,提升了读写性能,尤其是在读多写少的场景下。
核心特性:
- 写锁(write lock):独占模式的锁,和
ReentrantLock类似,保证写操作的排他性。 - 悲观读锁(read lock):共享模式的锁,多个线程可以同时持有读锁,但写锁需要等待。
- 乐观读锁(optimistic read lock):无需阻塞的读锁机制,允许在没有竞争的情况下进行快速读取。当检测到有写操作发生时,才会回退到悲观读锁或重试。
时间戳(stamp):
- 每个锁操作都会返回一个 stamp,代表了锁的状态,后续操作需要根据这个 stamp 来验证锁是否有效。
扩展知识
StampedLock 的优缺点
优点:
- 乐观读模式提供了更高效的并发读操作,避免了传统锁机制下的线程阻塞。
- 更灵活的锁机制,允许不同的锁模式进行切换,适合不同场景。
缺点:
- 不可重入:
StampedLock是非重入锁,这意味着同一个线程不能在持有锁时再次获取同类型的锁,否则会造成死锁。 - 读锁饥饿:在高写入负载的场景下,悲观读锁可能会被长期阻塞,导致读操作饥饿。
- CPU飙升风险:如果线程使用
writeLock()或者readLock()获得锁之后,线程还没执行完就被interrupt()的话,会导致CPU飙升,需要用readLockInterruptibly或者writeLockInterruptibly。
我本地跑了下复现了:

内部原理
StampedLock通过一个长整型值来管理状态,低位用于表示锁的类型(写锁、读锁),高位用于表示锁的计数。当乐观读锁被获取时,生成一个时间戳(stamp),并在后续验证时判断是否有写操作发生。validate(stamp)方法可以有效判断在持有乐观读锁的情况下,是否有其他写操作干扰(被修改了),从而决定是否要变为悲观读锁。
代码示例:
1 | import java.util.concurrent.locks.StampedLock; |
关键点:
- 写锁用于修改共享资源,多个线程无法同时持有写锁。
- 悲观读锁保证数据一致性,适合写操作较多的场景。
- 乐观读锁适用于读多写少的场景,可以在大部分时间无锁读取,大大提高性能。
Comments