trylock 本身不能直接避免死锁,但通过超时机制、固定顺序加锁、及时释放已持锁等策略可降低死锁风险;它提供非阻塞加锁能力,使线程能主动打破循环等待条件。

tryLock 方法本身不能直接避免死锁,但它提供了控制锁获取行为的手段,配合合理设计才能降低死锁风险。
理解 tryLock 与死锁的关系
死锁是多个线程互相等待对方持有的锁,形成循环等待。tryLock 属于 ReentrantLock 的非阻塞式加锁方式,它不会无限等待,而是立即返回成功或失败结果。这为程序争取了主动权——一旦获取失败,可以决定放弃、重试、回退或释放已持锁,从而打破死锁形成的必要条件(循环等待)。
用超时机制打断无限等待
调用 tryLock(long timeout, TimeUnit unit) 设置合理超时时间,避免线程卡在锁请求上:
- 超时后返回
false,线程可执行清理逻辑(如释放已占资源),再退出或重试 - 超时值需权衡:太短易频繁失败,太长仍可能陷入临时僵局
- 示例:
if (!lock.tryLock(100, TimeUnit.MILLISECONDS)) { /* 放弃或降级处理 */ }
按固定顺序获取多把锁
即使使用 tryLock,若多个线程以不同顺序申请同一组锁,仍可能因竞争时序引发死锁。解决方法是约定全局一致的加锁顺序:
- 根据锁对象的哈希值或唯一 ID 排序,确保所有线程按相同顺序调用 tryLock
- 只在确认前序锁全部获取成功后,才尝试下一把锁
- 任一锁获取失败,立即释放已持锁并终止流程(避免持有部分锁阻塞他人)
避免嵌套锁与锁升级
tryLock 不适用于递归重入场景(除非明确使用公平/非公平策略且允许重入),更不应在已持锁情况下再用 tryLock 获取另一把锁而忽略失败处理:
- 持有锁 A 时 tryLock B 失败,必须释放 A 再退出,否则 A 成为“孤儿锁”阻碍其他线程
- 不要在 synchronized 块内混用 tryLock,二者锁机制不互通,无法形成统一协调
- 优先考虑无锁设计(如原子类、CAS 操作)或更高级并发结构(如
StampedLock的乐观读)
不复杂但容易忽略:死锁预防靠的是协议和纪律,tryLock 只是提供了一个可中断、可判断的工具。真正起作用的是你如何用它做决策。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











