reentrantlock的重入计数器复用aqs的state字段:state==0表示空闲,state>0即重入次数;同一线程可多次cas递增state,仅当state减至0才释放锁并唤醒等待者。

ReentrantLock 的重入能力依赖于内部的 锁持有计数器(hold count),它记录当前线程获取该锁的次数。这个计数器不是全局共享的,而是以 线程私有方式存储,核心实现靠的是 AQS(AbstractQueuedSynchronizer) 的 state 字段配合线程身份识别。
计数器存在哪里?
计数器本身不单独分配对象,而是复用 AQS 的 state 整型字段:
- 当锁未被占用时,
state == 0 - 当某线程首次获取锁,
state变为 1 - 同一线程再次调用
lock(),state递增(如变为 2、3…) - 每次
unlock(),state递减,直到归零才真正释放锁
如何区分“谁持有锁”?
仅靠 state 无法判断是否可重入,必须知道当前持有者是不是自己。ReentrantLock 在加锁时会:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 检查
state是否为 0:是 → 尝试 CAS 设置为 1,并记录当前线程为exclusiveOwnerThread - 检查
state > 0且exclusiveOwnerThread == currentThread:是 → 直接递增state,完成重入 - 否则说明被其他线程持有,当前线程需排队或失败(取决于公平性策略)
可重入的关键逻辑在 tryAcquire 方法里
以非公平锁为例,NonfairSync.tryAcquire(int acquires) 的核心逻辑是:
- 先尝试一次 CAS 获取(无视排队),成功则设置 owner 并返回 true
- 若发现锁已被当前线程持有(owner 匹配),直接增加 state,不走 CAS 竞争
- state 增量固定为 1(acquires 参数恒为 1),所以每次 lock() 都使计数器 +1
解锁时只减不删,直到归零才清空 owner
tryRelease(int releases) 中:
- 先校验当前线程是否为持有者,不是则抛
IllegalMonitorStateException - 用
state - releases更新值(releases 恒为 1) - 新 state 为 0 时,才将
exclusiveOwnerThread设为 null,表示锁完全释放 - 只要 state > 0,即使 unlock() 多次,也只减计数,不会提前释放锁
不复杂但容易忽略:重入计数器本质是“线程 ID + state 值”的绑定,不是独立变量,也不依赖 ThreadLocal 存储,所有状态都收敛在 AQS 实例内。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










