reentrantreadwritelock 的核心价值在于用32位state分离读写管理:高16位计读锁重入次数,低16位计写锁重入次数;读读并发、读写/写写互斥,支持锁降级但不支持升级。

ReentrantReadWriteLock 的核心价值,就在于它用一套状态机制,在高并发场景下把“读”和“写”真正分开管理——读可以并发,写必须独占,读写之间严格互斥。
读-读不互斥:并发读的底层支撑
多个线程同时获取读锁是被允许的,这是提升吞吐量的关键。它的实现不是靠额外维护一组读线程列表,而是复用 AQS 的 共享模式:只要当前没有写锁(即 state 的低16位为 0),读线程就能成功更新 state 的高16位(读计数加一)。
- 读锁可重入:同一线程多次 acquire 读锁,state 高16位递增;对应地,unlock 次数必须匹配,否则高16位不会归零
- 读锁数量有上限:高16位最大值为 65535,超过会溢出导致异常,实际中极少达到
- 读操作期间,其他读线程无需等待,直接进入临界区执行,显著降低响应延迟
读-写与写-写严格互斥:数据一致性的保障
写锁采用 AQS 的 独占模式,一旦持有,就阻塞所有新读请求和新写请求。这种互斥不是靠逻辑判断,而是嵌入在 state 更新的原子性检查中:
- 写锁申请时,要求整个 state 为 0(无读无写)或仅由当前线程持有读锁(支持锁降级)
- 读锁申请时,必须确保低16位(写锁计数)为 0,否则进入同步队列等待
- 写锁本身可重入,但同一时刻最多一个线程持有;重入次数记录在低16位,上限也是 65535
状态编码:32位 int 的精妙分工
ReentrantReadWriteLock 不用两个变量,只靠一个 int 类型的 state 就管住两类锁,关键在于位拆分:
- 高16位(bits 16–31):表示当前持有读锁的总次数(非线程数,含重入)
- 低16位(bits 0–15):表示当前写锁的重入次数(0 表示未持有)
- 工具方法如
sharedCount(c)和exclusiveCount(c)就是通过位运算提取对应部分
锁降级:写锁→读锁的可控让渡
这是 ReentrantReadWriteLock 提供的一个特殊能力:持有写锁的线程,在未释放写锁的前提下,可以直接获取读锁,然后释放写锁,从而“降级”为只读状态。
- 降级过程必须由同一个线程完成,且中间不能有其他线程插队获取写锁
- 它常用于“先修改、再立即读取结果”的场景,避免释放写锁后被其他写线程抢占导致数据不一致
- 注意:升级(读锁→写锁)不被支持,否则必然引发死锁
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











