ReadWriteLock的读锁在无写锁时允许多线程并发读取,实现读操作并行化,显著提升吞吐量;其本质是共享锁,依赖AQS高位状态计数,支持重入但禁止锁升级,适用于读多写少场景。

ReadWriteLock 的读锁在没有写锁时能显著提升并发,核心在于允许多个线程同时持有读锁,实现真正的读操作并行化——只要不涉及写入,读线程之间互不阻塞。
读锁共享:多个读线程可同时进入临界区
与独占式 ReentrantLock 不同,ReadWriteLock(如 ReentrantReadWriteLock)的读锁是“共享锁”。当没有线程持有写锁时,任意数量的读线程可以同时成功 acquire 读锁,无需排队等待。
- 读操作不修改共享状态,因此多个读线程并发访问是安全的
- 底层通过 AQS 的 state 字段高位记录读锁计数,支持重入和计数管理
- 相比用单个 ReentrantLock 包裹全部读写操作,读吞吐量可随 CPU 核心数线性增长(受限于缓存一致性开销)
写锁排斥读锁:但读锁不排斥其他读锁
读锁的并发优势依赖“无写锁”的前提。一旦有线程尝试获取写锁,后续读锁请求会被阻塞,直到写锁释放;但已持有的读锁不会被强制中断,保证读操作的完整性。
- 写锁获取需等待所有已有读锁释放,体现“写优先”或“公平策略”(取决于构造参数)
- 读锁释放不唤醒写锁线程(除非是最后一个读锁),避免写饥饿;但新读线程仍可继续获取读锁(非公平模式下)
- 典型场景:高频查询 + 低频更新的配置缓存、元数据目录,读锁并发直接降低平均响应延迟
避免锁升级:读锁不能直接转为写锁
这是保障并发安全的关键设计。如果允许读锁升级为写锁,会导致死锁风险(其他读线程可能正等待该写锁),因此必须先释放读锁再申请写锁。
立即学习“Java免费学习笔记(深入)”;
- 常见错误:在持有读锁时调用 writeLock().lock() → 必然阻塞甚至死锁
- 正确做法:判断是否需要写入 → 释放 readLock → 获取 writeLock → 检查条件是否仍成立(防止竞态)→ 执行写入
- 这种“检查-释放-加锁-再检查”模式虽增加开销,但换来确定的并发安全性
合理粒度与锁降级:进一步优化读写协作
单纯依赖读锁共享还不够,需配合业务逻辑控制锁的作用范围,并善用锁降级(writeLock → readLock)来减少写锁持有时间。
- 读锁尽量只包裹纯读取逻辑,避免在 readLock 内做耗时计算或 I/O
- 锁降级示例:先用 writeLock 更新缓存 → 立即降级为 readLock → 允许其他线程并发读取新值,缩短写锁窗口
- 注意:锁降级仅支持 writeLock → readLock,且必须按顺序连续执行,不可跨线程或中间插入其他操作


















