reentrantreadwritelock 的核心逻辑是分离读写操作:读锁共享允许多线程并发,写锁独占确保排他性;通过 state 高16位计数读锁、低16位计数写锁;支持锁降级但禁止锁升级。

ReentrantReadWriteLock 的核心逻辑在于把“读”和“写”两类操作彻底分开管理,不是简单地加一层锁,而是用一套协同机制让读与读并行、读与写互斥、写与写独占。
读锁是共享的,允许多线程同时进入
读操作本身不改变数据,多个线程读同一份内容不会引发一致性问题。ReentrantReadWriteLock 的读锁设计为共享锁(Shared Lock),只要当前没有线程持有写锁,任何数量的读线程都可以成功获取读锁并并发执行。
- 内部通过 state 变量的高 16 位计数:每获取一次读锁,高位加 1;释放一次,高位减 1
- 同一线程可重入多次读锁,计数累加,需对应次数 unlock 才真正释放
- 读锁获取时会检查:低 16 位(写锁计数)是否为 0,且当前无写线程正在排队(公平模式下还需看队列头)
写锁是独占的,阻塞所有其他读写请求
写操作会修改共享状态,必须确保排他性。写锁是典型的排他锁(Exclusive Lock),一旦被某个线程持有,其他所有试图获取读锁或写锁的线程都会被挂起等待。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 写锁状态由 state 的低 16 位维护:记录当前持有写锁的线程重入次数
- 获取写锁前,必须确认:无活跃读锁(高位为 0)、无其他写线程持有锁、且写锁等待队列中没有更高优先级的读线程(公平模式)
- 持有写锁的线程可以再次 lock() 写锁(可重入),也可以在不释放写锁的前提下获取读锁(锁降级)
读写之间严格互斥,靠状态协同判断
读写互斥不是靠“谁先谁后”的粗粒度排队,而是基于 state 的实时状态做原子判断:
- 读锁获取时:要求写锁计数为 0,且写锁未被占用(即 writeHoldCount == 0)
- 写锁获取时:要求读锁计数为 0(即 no reader),且写锁未被占用
- 这种检查发生在 AQS 的 tryAcquireShared / tryAcquire 方法中,底层依赖 CAS 操作保证原子性
支持锁降级但禁止锁升级
这是保障线程安全的关键设计约束:
- 允许“写 → 读”降级:持有写锁后,可直接获取读锁,再释放写锁,从而平滑过渡到只读状态(常用于更新后立即读取最新值)
- 禁止“读 → 写”升级:已持读锁的线程不能直接获取写锁,否则会引发死锁风险(例如:多个读线程都等对方释放读锁来抢写锁)
- 若需从读转写,必须先释放读锁,再尝试获取写锁——这中间存在数据被其他写线程修改的窗口期,业务需自行处理校验(如 double-check)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










