ReentrantLock支持安全重入,通过线程专属持有者标识和holdCount计数器实现;每次lock()增加计数,仅当unlock()使计数归零才真正释放锁;需严格配对lock/unlock并置于finally中。

ReentrantLock 本身不“防止”重入,而是设计为支持安全重入——它通过线程专属的持有者标识 + 精确计数机制,确保同一线程多次加锁/解锁不会引发计数混乱或资源错乱。
重入计数由线程隔离保障
每个 ReentrantLock 内部维护两个关键状态:
- 当前持有锁的线程引用(仅记录一个线程,不是线程列表)
- 该线程专属的重入计数器(
holdCount),初始为 0
当线程 A 调用 lock() 时:
- 若锁空闲 → 设置持有者为 A,计数器置为 1
- 若持有者已是 A → 计数器直接 +1(不阻塞、不变更持有者)
- 若持有者是其他线程 B → 当前线程 A 进入等待队列
释放操作严格匹配获取次数
unlock() 不是“释放锁”,而是“减少当前持有线程的计数”:
立即学习“Java免费学习笔记(深入)”;
- 每次调用只将
holdCount减 1 - 仅当减至 0 时,才清除持有者、唤醒等待队列中的第一个线程
- 若计数未归零就调用
unlock(),会抛出IllegalMonitorStateException
计数溢出有明确边界和防护
Java 中 holdCount 是 int 类型,最大值为 Integer.MAX_VALUE(2147483647):
- 达到上限后再次
lock(),会抛出Error(非 Exception),如OutOfMemoryError或自定义错误 - 这属于严重编程错误信号,提示存在无限递归加锁、漏释放等逻辑缺陷
- 正常业务中几乎不可能触达该上限,无需主动防御,但需避免无终止的嵌套加锁
真正需要你控制的是释放时机,不是计数本身
计数逻辑由锁内部全自动管理,开发者唯一要确保的是:
- 每次
lock()都必须配对一次unlock(),且都在finally块中执行 - 不要跨方法、跨异常分支遗漏
unlock(),否则计数无法归零,锁永远不释放 - 避免在持有锁期间调用不可控的外部方法(如回调、IO),以防中途抛异常导致
finally未执行


















