ReentrantLock 本身不降低死锁概率,但通过统一加锁顺序、tryLock超时、lockInterruptibly可中断、避免锁内调用外部方法等策略可有效减少死锁。

ReentrantLock 本身不能直接“降低死锁概率”,但它提供了比 synchronized 更精细的控制能力,配合合理使用策略(如锁顺序、超时、可中断等待等),才能有效减少死锁发生的机会。
统一加锁顺序
多个线程按相同顺序获取多个锁,是预防死锁最根本的方法。ReentrantLock 支持显式 lock() 和 unlock(),便于在代码中明确控制加锁顺序。
- 为所有共享资源定义全局唯一编号(如按对象哈希码或业务 ID 排序)
- 每次需要多把锁时,始终按编号从小到大依次 acquire
- 避免在不同方法中以不同顺序调用 lock(),尤其注意嵌套调用场景
使用 tryLock() 设置超时
相比无条件阻塞的 lock(),tryLock(long, TimeUnit) 允许线程在指定时间内获取锁,超时则放弃并释放已持锁,打破循环等待条件。
- 获取第一把锁成功后,再用 tryLock(100, MILLISECONDS) 尝试第二把锁
- 若失败,立即 unlock() 已持有的锁,回退或重试,不持续等待
- 注意:必须在 finally 块中 unlock(),否则可能因异常导致锁泄漏
优先使用可中断锁等待
lockInterruptibly() 让线程在等待锁时响应 interrupt(),便于外部主动终止等待,避免无限期阻塞。
立即学习“Java免费学习笔记(深入)”;
- 适合长时间运行且需支持取消的任务(如后台服务、批量处理)
- 捕获 InterruptedException 后,应清理资源并释放已持锁
- 与 Thread.interrupt() 配合,实现协作式中断机制
避免锁内调用外部不可控方法
ReentrantLock 不会自动防止锁内调用未知代码(如回调、接口实现),而这些方法可能反过来请求其他锁,引发隐式锁顺序混乱。
- 锁区内只做确定性操作:读写本对象字段、简单计算、调用 final 方法
- 如需调用外部方法,先释放锁,再调用;必要时复制数据供外部使用
- 警惕日志、监控、事件通知等看似安全的操作,它们可能间接触发锁竞争


















