读写锁(ReentrantReadWriteLock)
读写锁是针对读多写少场景的优化。多个线程可以同时读取,但写操作需要独占访问。ReentrantReadWriteLock 实现了读锁和写锁的分离,能显著提升读密集型系统的吞吐量。
为什么需要读写锁
场景分析
性能对比
锁的互斥规则
基本规则
状态表示
ReentrantReadWriteLock 使用 AQS 的 state 高低位分离表示锁计数:
基本用法
创建和获取
读写锁的升级
注意:ReentrantReadWriteLock 不支持从读锁直接升级到写锁,这会导致死锁。
写锁 -> 读锁:锁降级
公平性
公平锁
公平模式下,等待时间最长的线程优先获取锁。
非公平锁
非公平模式下,新线程可能插队。但读锁是共享的,所以非公平读写锁的读性能通常比公平版本好。
锁状态监控
应用场景
缓存
读写分离的数据结构
StampedLock 简介
JDK 8 引入了 StampedLock,提供乐观读锁,比 ReentrantReadWriteLock 的读锁更轻量。
特点
- 乐观读锁:假设没有写操作,直接读取;如果发现被修改则升级为读锁
- 更高效:读操作不需要 CAS
- 支持写锁升级:可以从乐观读升级为写锁
示例
本章总结
核心要点:
- 读写锁分离:读锁共享,写锁独占
- 适用场景:读多写少的数据访问
- 锁升级:不支持读锁升级为写锁(会死锁)
- 锁降级:支持写锁降级为读锁
- StampedLock:更轻量的读写锁,支持乐观读
- 注意:读写锁的获取和释放必须配对
读写锁是读多写少场景的利器。下一节我们将讲解 StampedLock 的更多细节。