ReentrantLock 的 lock 和 unlock 必须成对出现在 try-finally 中,lock() 阻塞获取锁,unlock() 必须由同一线程调用;支持 tryLock、lockInterruptibly 和 Condition 等增强功能,适用于需公平性、可中断、多等待队列等场景。

ReentrantLock 的 lock 和 unlock 必须成对出现,且必须在 try-finally 块中使用,否则一旦代码抛异常,unlock 就不会执行,锁无法释放,导致其他线程永久阻塞。
加锁与释放的基本写法
标准用法是先调用 lock() 获取锁,再把业务逻辑放在 try 块中,最后在 finally 中调用 unlock():
- lock() 是阻塞式获取锁,如果锁被占用,当前线程会一直等待
- unlock() 必须由持有锁的线程调用,否则抛
IllegalMonitorStateException - 即使业务逻辑中发生 RuntimeException 或 Error,finally 仍会执行,确保锁被释放
避免常见错误的要点
手动控制锁容易出错,关键注意三点:
- 不能只在 try 里 lock,不配 finally unlock —— 异常时锁就漏了
- 不能把 unlock 放在 try 里 —— 可能提前释放,破坏临界区保护
- 不能在不同线程间传递锁的 ownership —— unlock 必须由 lock 的同一个线程执行
可选的增强控制方式
除了基础 lock/unlock,ReentrantLock 还提供更精细的控制能力:
-
tryLock():非阻塞尝试获取锁,成功返回 true,失败立即返回 false -
tryLock(long, TimeUnit):最多等待指定时间,超时或中断则放弃 -
lockInterruptibly():可响应中断的阻塞获取,被中断时抛 InterruptedException - 配合
newCondition()实现条件等待,比 Object 的 wait/notify 更灵活
为什么不用 synchronized?
synchronized 是 JVM 自动管理的,异常时自动释放;而 ReentrantLock 是显式锁,灵活性高但责任也重。适合需要以下能力的场景:
- 按需设置公平性(公平锁 / 非公平锁)
- 限时等待、可中断等待
- 一个锁对应多个等待队列(多个 Condition)
- 查询锁状态,如
isLocked()、getHoldCount()等诊断方法










