ReentrantLock通过tryLock(long timeout, TimeUnit unit)支持带超时的加锁,超时未获锁返回false而非抛异常,需配合finally中unlock确保释放;超时值应依业务合理设定,避免过长掩盖性能问题。

ReentrantLock 支持带超时的加锁,主要通过 tryLock(long timeout, TimeUnit unit) 方法实现,它会在指定时间内尝试获取锁,超时未获得则返回 false,避免无限阻塞。
使用 tryLock 带超时参数获取锁
这是最常用的方式,需显式传入等待时间和时间单位。与无参 tryLock()(立即返回)不同,它允许你控制最大等待时长:
- 返回
true表示成功获取锁,可安全执行临界区逻辑 - 返回
false表示超时未获取到锁,应放弃或重试,**不会抛异常** - 必须配合
lock.unlock()使用,且推荐放在finally块中确保释放
典型使用模板(避免死锁和资源泄漏)
务必遵循“获取锁 → 执行业务 → 必须释放”的结构,尤其注意异常情况下的解锁保障:
ReentrantLock lock = new ReentrantLock();
boolean locked = false;
try {
// 尝试最多等待 3 秒
locked = lock.tryLock(3, TimeUnit.SECONDS);
if (!locked) {
System.out.println("获取锁超时,跳过操作");
return;
}
// 执行受保护的业务逻辑
doSomethingCritical();
} finally {
if (locked) {
lock.unlock(); // 只有真正拿到锁才释放
}
}
超时时间设置的实用建议
超时值不是越长越好,需结合业务场景权衡:
立即学习“Java免费学习笔记(深入)”;
- 短耗时操作(如更新内存缓存):建议 100–500 毫秒
- 涉及轻量 I/O 或简单计算:1–3 秒较常见
- 避免设为过长(如 30 秒以上),否则失去“超时”意义,可能掩盖性能问题
- 若频繁超时,应检查锁竞争是否严重、临界区是否过重,而非单纯调大超时
与 synchronized 对比的关键差异
ReentrantLock 的超时能力是 synchronized 不具备的:
-
synchronized是阻塞式,无法设定等待上限,一旦被阻塞就只能等锁释放 -
tryLock让线程具备“主动放弃”的能力,更适合高并发、低延迟或需快速失败的场景 - 但要注意:ReentrantLock 需手动管理锁的获取与释放,出错易导致死锁或资源泄漏


















