ReentrantLock 的可重入特性通过 state 计数器和 exclusiveOwnerThread 线程标识实现:同一线程重复 lock() 时 state 加 1,unlock() 时减 1,仅当 state 为 0 才真正释放锁;必须成对调用且限于同一线程。

ReentrantLock 的可重入特性是通过内部的同步状态(state)和持有锁的线程标识(exclusiveOwnerThread)共同实现的,不是靠递归调用或额外数据结构,而是靠计数器 + 线程身份比对。
可重入的核心原理
ReentrantLock 在加锁时会检查当前持有锁的线程是否就是当前请求锁的线程:
- 如果是,就将同步状态(state)值加 1,表示该线程已重入一次;
- 如果不是,且锁已被占用,则当前线程进入等待队列;
- 释放锁时,state 减 1,只有当 state 变为 0 时才真正释放锁,并清空 exclusiveOwnerThread。
正确使用 lock() 和 unlock() 实现可重入
必须成对调用,且在同一线程内多次 lock() 才体现可重入。例如:
ReentrantLock lock = new ReentrantLock();
public void doSomething() {
lock.lock(); // 第一次获取锁
try {
// 业务逻辑
innerMethod();
} finally {
lock.unlock(); // 对应第一次 lock()
}
}
public void innerMethod() {
lock.lock(); // 同一线程再次 lock() —— 可重入成功
try {
// 嵌套逻辑
} finally {
lock.unlock(); // 对应本次 lock()
}
}
注意:每次 lock() 都必须有对应的一次 unlock(),否则 state 不归零,锁无法被其他线程获取。
立即学习“Java免费学习笔记(深入)”;
避免常见误用
- 不要在不同线程间共享同一个 lock 实例并期望“重入”,可重入只对同一线程有效;
- 不要在 try 块外调用 lock(),也不要在 catch 中 unlock(),必须用 finally 或 try-with-resources(配合 LockSupport 或自定义封装)确保释放;
- 不可重入场景(如用两个不同 ReentrantLock 实例嵌套)不构成可重入,只是普通并发控制。
查看重入次数与持有线程
可通过 API 辅助调试:
- getHoldCount():返回当前线程持有此锁的次数;
- getOwner():返回当前持有锁的线程(可能为 null);
- isHeldByCurrentThread():判断当前线程是否持有此锁。
这些方法有助于验证可重入行为是否符合预期,比如在递归调用中打印 holdCount 能直观看到计数变化。


















