ReentrantLock与显式锁
一、ReentrantLock 使用与 API
核心使用流程:
手动加锁、手动解锁,必须在 finally 释放锁,避免死锁。
1 | |
核心 API
lock():阻塞式加锁,拿不到锁一直等待,不可中断lockInterruptibly():可中断加锁,等待时响应中断tryLock():非阻塞尝试抢锁,抢到返回 true,失败直接 falsetryLock(timeout, unit):超时抢锁,限时内没拿到就返回 falseunlock():释放锁newCondition():生成 Condition,实现精准唤醒
二、公平锁与非公平锁实现
- 构造方法
new ReentrantLock():非公平锁(默认)new ReentrantLock(true):公平锁
- 非公平锁
- 线程抢锁时,先直接 CAS 插队抢占 state,不排队
- 抢不到才进入 CLH 队列排队
- 优点:吞吐量高、竞争小;缺点:可能出现线程饥饿
- 公平锁
- 线程抢锁前,先判断 CLH 等待队列是否有排队线程
- 有等待队列直接入队,严格 FIFO,禁止插队
- 优点:绝对公平、无饥饿;缺点:上下文切换多,性能偏低
- 底层共性
- 二者都基于 AQS 独占模式实现,都支持可重入。
三、ReentrantLock 与 synchronized 对比
- 底层实现
- synchronized:JVM 原生锁,对象头 MarkWord,偏向锁→轻量级锁→重量级锁
- ReentrantLock:JDK 代码实现,基于 AQS+CAS+CLH 队列
- 可重入性
- 两者都支持可重入
- 功能灵活性
- synchronized:功能单一,不可中断、不能超时、无法精准唤醒
- ReentrantLock:支持中断、超时、tryLock、多 Condition 精准唤醒、公平 / 非公平切换
- 锁释放
- synchronized:自动解锁,代码执行完 / 异常自动释放
- ReentrantLock:手动 unlock,必须 finally 释放,否则永久死锁
- 性能
- JDK1.6 后 synchronized 优化充分,性能基本持平
- 高并发竞争场景下,ReentrantLock 可控性更强
四、tryLock、锁中断、超时获取
- tryLock () 无参
- 立即尝试 CAS 抢锁,不阻塞、不排队
- 抢到锁返回 true,抢不到直接返回 false
- 用于防止死锁、快速失败业务场景
- 可中断锁 lockInterruptibly ()
- 普通 lock () 阻塞等待时,无视中断
- lockInterruptibly () 等待期间收到线程中断信号,直接抛异常退出阻塞
- 适合需要主动终止等待的业务
- 超时获取 tryLock (时间,单位)
- 在指定时间内自旋抢锁,时间内抢到则成功
- 超时仍未获取锁,直接返回 false
- 避免无限阻塞,控制锁等待时长
极简总结
- ReentrantLock 是 AQS 独占显式锁,手动加解锁、支持重入;
- 非公平插队高性能,公平排队防饥饿;
- 比 synchronized 功能更强:可中断、超时、尝试锁、精准唤醒;
- 三大高级特性:tryLock 非阻塞、lockInterruptibly 可中断、超时限时等待。
ReentrantLock与显式锁
http://hanqichuan.com/2026/04/15/java并发/ReentrantLock与显式锁/