trylock() 更适合超时控制场景,因为它可立即返回成功或失败,避免线程无限阻塞;而 lock() 会一直等待直至获取锁,无法主动退出。

tryLock() 为什么比 lock() 更适合超时控制场景
当线程需要获取锁但又不能无限等待时,ReentrantLock.tryLock() 是唯一能主动退出等待的方案。它不会像 lock() 那样陷入阻塞态,而是立即返回 true 或 false,把决策权交给调用方。这对高并发下避免线程饥饿、实现降级逻辑(比如缓存未命中时查 DB)、或构建非阻塞算法非常关键。
注意:tryLock() 默认不带参数是「非公平+无等待」语义——即只尝试一次,不排队也不等,哪怕锁刚被释放也可能抢不到(因其他线程抢先)。
带超时的 tryLock(long, TimeUnit) 怎么用才可靠
要真正实现“最多等 N 秒”,必须用带两个参数的重载:tryLock(long timeout, TimeUnit unit)。它会在指定时间内轮询锁状态,若超时仍未获取成功,返回 false,且**不会持有任何锁资源**。
- 超时时间设为
0等价于无参tryLock() - 超时单位别写错,例如
TimeUnit.SECONDS和TimeUnit.MILLISECONDS差 1000 倍 - 该方法可能被中断,抛出
InterruptedException,必须显式处理,否则会丢失中断信号 - 即使超时返回
false,也不能假设锁一定被别人持有着——可能只是当前无人持有,但下一纳秒就被别的线程抢走
示例:
ReentrantLock lock = new ReentrantLock();
if (lock.tryLock(3, TimeUnit.SECONDS)) {
try {
// 执行临界区逻辑
} finally {
lock.unlock();
}
} else {
// 超时未获取到锁,走备选路径(如返回默认值、记录告警)
}
tryLock() 后忘记 unlock() 会导致什么
这是最隐蔽也最致命的问题:如果 tryLock() 返回 true,说明你已成功获得锁,就必须配对调用 unlock();否则锁永远不会释放,后续所有线程都会在 tryLock() 上失败,系统逐步退化为单线程。
常见错误模式:
- 在
try块里tryLock()成功,但没用finally保证unlock() - 临界区抛异常后直接跳出,
unlock()被跳过 - 误以为
tryLock()失败就不用管锁,其实失败时根本没拿到锁,unlock()会抛IllegalMonitorStateException
正确姿势永远是:tryLock() 成功 → 进入 try-finally → finally 中调用 unlock()。
公平锁模式下 tryLock() 的行为差异
创建锁时传 true(如 new ReentrantLock(true))启用公平模式,此时 tryLock()(无参)仍**不遵循队列顺序**——它依然只尝试抢占,不排队。只有 lock() 才严格按 FIFO 入队等待。
这意味着:在公平锁下,tryLock() 可能绕过等待队列直接抢到锁,破坏公平性承诺。如果你依赖公平性做资源调度,就不要在公平锁上混用 tryLock(),否则队列形同虚设。
另外,公平锁的 tryLock(long, TimeUnit) 在超时等待期间会遵守队列顺序,但前提是它进入等待前已排上队——而这个“入队时机”由 JVM 实现细节决定,不可控。所以生产环境慎用公平锁 + tryLock 组合。
真正需要公平性的场景,通常应避免使用 tryLock(),改用带中断支持的 lockInterruptibly() 配合合理超时策略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











