可重入锁允许同一线程多次获取同一把锁而不阻塞,通过持有计数器和独占线程标识实现;支持公平/非公平模式;需手动释放且必须在finally中调用unlock();具备可中断、尝试获取、超时获取及多条件变量等synchronized不具备的能力。

可重入锁,就是同一个线程可以反复获取同一把锁而不被自己阻塞的锁。
可重入性是怎么工作的
ReentrantLock 内部维护一个持有计数器(hold count)和一个独占线程标识(exclusiveOwnerThread)。当线程第一次调用 lock() 时,计数器设为 1,线程被记录为持有者;再次调用 lock(),计数器加 1;每次 unlock() 都减 1。只有计数器归零时,锁才真正释放,其他线程才有机会抢到。
这种机制让递归调用、嵌套同步逻辑成为可能,比如外层方法加锁后调用内层也需加同一把锁的方法,不会卡死。
公平锁与非公平锁的区别
ReentrantLock 构造时可传 boolean fair 参数:
立即学习“Java免费学习笔记(深入)”;
- 非公平锁(默认):允许刚释放锁的线程或新来的线程“插队”,吞吐量高,但可能造成个别线程长时间等待(饥饿)
- 公平锁(new ReentrantLock(true)):按线程入队顺序分配锁,更公平,但上下文切换多、性能略低
注意:公平锁不保证调度公平,也不影响 tryLock() 行为——它始终是非公平的,即使在公平锁实例上调用。
必须手动释放 + 正确写法
和 synchronized 不同,ReentrantLock 是显式锁,必须配对使用 lock() 和 unlock(),且 unlock() 必须放在 finally 块里,否则一旦临界区抛异常,锁就永远无法释放。
标准写法是:
lock.lock();
try {
// 业务代码
} finally {
lock.unlock();
}
比 synchronized 多出来的实用能力
- 可中断获取锁:用 lockInterruptibly(),线程等待时能响应 interrupt()
- 尝试获取锁:tryLock() 立即返回 true/false,适合避免阻塞或做降级处理
- 超时获取锁:tryLock(2, TimeUnit.SECONDS),防止无限等待
- 绑定多个条件变量:通过 lock.newCondition() 创建独立的 await/signal 队列,比 wait/notify 更精准
基本上就这些。










