ReentrantLock与显式锁

一、ReentrantLock 使用与 API

核心使用流程:

手动加锁、手动解锁,必须在 finally 释放锁,避免死锁。

1
2
3
4
5
6
7
ReentrantLock lock = new ReentrantLock();
lock.lock(); // 加锁
try {
// 临界区业务
} finally {
lock.unlock(); // 释放锁
}

核心 API

  • lock():阻塞式加锁,拿不到锁一直等待,不可中断
  • lockInterruptibly():可中断加锁,等待时响应中断
  • tryLock():非阻塞尝试抢锁,抢到返回 true,失败直接 false
  • tryLock(timeout, unit):超时抢锁,限时内没拿到就返回 false
  • unlock():释放锁
  • newCondition():生成 Condition,实现精准唤醒

二、公平锁与非公平锁实现

  1. 构造方法
  • new ReentrantLock()非公平锁(默认)
  • new ReentrantLock(true)公平锁
  1. 非公平锁
  • 线程抢锁时,先直接 CAS 插队抢占 state,不排队
  • 抢不到才进入 CLH 队列排队
  • 优点:吞吐量高、竞争小;缺点:可能出现线程饥饿
  1. 公平锁
  • 线程抢锁前,先判断 CLH 等待队列是否有排队线程
  • 有等待队列直接入队,严格 FIFO,禁止插队
  • 优点:绝对公平、无饥饿;缺点:上下文切换多,性能偏低
  1. 底层共性
  • 二者都基于 AQS 独占模式实现,都支持可重入。

三、ReentrantLock 与 synchronized 对比

  1. 底层实现
  • synchronized:JVM 原生锁,对象头 MarkWord,偏向锁→轻量级锁→重量级锁
  • ReentrantLock:JDK 代码实现,基于 AQS+CAS+CLH 队列
  1. 可重入性
  • 两者都支持可重入
  1. 功能灵活性
  • synchronized:功能单一,不可中断、不能超时、无法精准唤醒
  • ReentrantLock:支持中断、超时、tryLock、多 Condition 精准唤醒、公平 / 非公平切换
  1. 锁释放
  • synchronized:自动解锁,代码执行完 / 异常自动释放
  • ReentrantLock:手动 unlock,必须 finally 释放,否则永久死锁
  1. 性能
  • JDK1.6 后 synchronized 优化充分,性能基本持平
  • 高并发竞争场景下,ReentrantLock 可控性更强

四、tryLock、锁中断、超时获取

  1. tryLock () 无参
  • 立即尝试 CAS 抢锁,不阻塞、不排队
  • 抢到锁返回 true,抢不到直接返回 false
  • 用于防止死锁、快速失败业务场景
  1. 可中断锁 lockInterruptibly ()
  • 普通 lock () 阻塞等待时,无视中断
  • lockInterruptibly () 等待期间收到线程中断信号,直接抛异常退出阻塞
  • 适合需要主动终止等待的业务
  1. 超时获取 tryLock (时间,单位)
  • 在指定时间内自旋抢锁,时间内抢到则成功
  • 超时仍未获取锁,直接返回 false
  • 避免无限阻塞,控制锁等待时长

极简总结

  1. ReentrantLock 是 AQS 独占显式锁,手动加解锁、支持重入;
  2. 非公平插队高性能,公平排队防饥饿;
  3. 比 synchronized 功能更强:可中断、超时、尝试锁、精准唤醒;
  4. 三大高级特性:tryLock 非阻塞、lockInterruptibly 可中断、超时限时等待。

ReentrantLock与显式锁
http://hanqichuan.com/2026/04/15/java并发/ReentrantLock与显式锁/
作者
韩启川
发布于
2026年4月15日
许可协议