ReentrantLock必须由加锁线程在持锁前提下释放,否则抛IllegalMonitorStateException;加锁与解锁须成对、同线程、先成功加锁再解锁,且unlock()必须置于finally块中确保执行。

ReentrantLock 必须在 持有锁的前提下释放,否则会抛出 IllegalMonitorStateException。核心原则是:**加锁与解锁必须成对、在同一线程中、且解锁前必须已成功加锁**。
确保只在已持有锁时调用 unlock()
ReentrantLock 不像 synchronized 那样自动管理锁的生命周期,它完全依赖开发者手动控制。常见错误是未校验是否真的获取到了锁就直接 unlock():
- 使用
lock.lock()(阻塞式)后,一定已持锁,此时可安全调用unlock() - 使用
lock.tryLock()时,必须检查返回值:仅当返回 true 时才可 unlock() - 若
tryLock()返回 false(未获取到锁),此时调用 unlock() 会立即抛异常
必须在 finally 块中释放锁
防止因异常导致 unlock() 被跳过,造成死锁或资源泄露:
- 不要把 unlock() 放在 try 或 catch 块里
- 无论是否发生异常,finally 是唯一可靠的位置
- 示例正确写法:
Lock lock = new ReentrantLock();
lock.lock();
try {
// 业务逻辑(可能抛异常)
} finally {
lock.unlock(); // 保证执行
}
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
立即学习“Java免费学习笔记(深入)”;
避免跨线程释放锁
ReentrantLock 是可重入、线程绑定的锁 —— 哪个线程加的锁,必须由同一个线程来释放:
- 不能在线程 A 中 lock(),在线程 B 中 unlock()
- 即使线程 B 持有该 Lock 实例引用,调用 unlock() 也会抛 IllegalMonitorStateException
- 异步任务、线程池回调等场景要特别注意锁的归属
慎用 lockInterruptibly() 后的释放逻辑
该方法响应中断,但加锁失败(被中断)时不会持有锁,因此不能无条件 unlock():
- 如果
lock.lockInterruptibly()抛出InterruptedException,说明根本没拿到锁 - 此时不应调用 unlock();只有捕获异常前已成功加锁,才需在 finally 中释放
- 更稳妥的做法仍是:用 tryLock() + 显式状态标记,或确保 lockInterruptibly() 在 try 外已成功执行

















