reentrantreadwritelock的写锁是独占的,基于aqs实现,通过state整型变量控制,支持重入且仅限同一线程,排斥所有读锁和其他写锁,公平性仅影响获取顺序而不改变其独占本质。

ReentrantReadWriteLock 的写锁是独占的,意味着同一时刻只允许一个线程持有写锁,且持有写锁时其他所有读锁和写锁都会被阻塞。
写锁基于 AQS 的独占模式实现
ReentrantReadWriteLock 的写锁底层复用 AbstractQueuedSynchronizer(AQS)的独占获取逻辑。它将同步状态(state)整体视为一个整型变量,写锁的获取与释放直接操作 state 的值,不区分高低位——这与读锁不同(读锁用 state 高 16 位计数)。当 state == 0 时,表示无任何锁被持有;当有线程成功获取写锁,state 被设为 1(重入时递增);释放时递减,直到归零。
- tryAcquire 方法判断:若 state 为 0,直接 CAS 设置为 1;若当前线程已持有写锁,则 state + 1(支持重入)
- 若 state ≠ 0 且当前线程不是持有者,获取失败,线程进入 AQS 同步队列等待
- 整个过程不关心读锁状态——只要 state ≠ 0(即已有写锁或读锁),写锁获取就会失败(除非是重入)
写锁排斥所有读锁和其它写锁
写锁的独占性体现在“写-写互斥”和“写-读互斥”两个层面:
- 写-写互斥:第二个写线程看到 state > 0 且持有者不是自己,立即失败并排队
- 写-读互斥:只要写锁被持有着(state ≥ 1),readLock().lock() 就会阻塞——因为读锁的 tryAcquireShared 会检查是否有写锁持有者(通过 getState() & 0xFFFF0000 != 0 判断高 16 位是否非零,但更关键的是:写锁持有期间,state 的低 16 位也可能非零,而读锁获取前会先验证“无写锁持有者”,即 compareAndSetState(0, r + 1) 失败)
- 注意:写锁获取不要求读锁已释放,而是直接禁止新读锁获取,并等待已有读锁全部释放后才能成功(即写锁需等待所有读线程退出)
可重入与持有者身份绑定
写锁是可重入的,但仅限同一线程。AQS 的 exclusiveOwnerThread 字段记录当前写锁持有者:
- 首次获取:state 从 0 → 1,exclusiveOwnerThread 设为当前线程
- 重入获取:检查当前线程是否等于 exclusiveOwnerThread,是则 state++
- 释放:state--,仅当 state 归零时才真正释放锁,并置 exclusiveOwnerThread 为 null
- 其他线程即使知道锁被持有着,也无法“偷取”或强制释放,完全依赖 AQS 的线程安全 CAS 和 volatile state 保障
公平性影响获取顺序,但不改变独占本质
构造 ReentrantReadWriteLock 时传入 true 可启用公平模式。此时写锁获取会检查同步队列中是否有等待节点——若有,则即使 state == 0 也不抢占,而是排队。但这只是调度策略调整,不削弱独占性:
- 非公平模式下,新写线程可能插队,但仍需满足“无锁占用”或“自己是持有者”条件
- 公平模式下,写线程严格按 FIFO 等待,但每次仍只唤醒一个,且唤醒后仍需通过 tryAcquire 检查合法性
- 无论是否公平,任意时刻最多一个线程能处于“已获取写锁”状态
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











