reentrantlock通过线程标识和state计数器实现可重入,支持公平/非公平策略;需手动配对lock/unlock,提供中断、超时等灵活控制,但责任更重。

Java高级锁机制中,可重入与公平锁的并发控制主要通过 ReentrantLock 实现。它不是语法糖,而是显式、可控、可配置的锁工具,核心在于理解“谁持有”“持有了几次”“按什么顺序排队”这三个关键点。
可重入锁:同一线程多次获取同一把锁不阻塞
可重入性解决的是嵌套调用或递归场景下的死锁风险。底层靠一个线程标识(exclusiveOwnerThread)加一个计数器(state)实现:
- 首次获取锁时,
state从 0 变为 1,并记录当前线程为持有者; - 同一线程再次调用
lock(),发现持有者是自己,就只将state+1; - 每次
unlock()都使state-1,只有减到 0 才真正释放锁,唤醒等待队列中的其他线程。
示例中,外层方法加锁后调用内层加锁方法,不会卡住——因为不是“有没有锁”,而是“是不是我自己的锁”。这和 synchronized 行为一致,但 ReentrantLock 允许你看见并干预这个过程。
公平锁:按申请顺序排队,避免插队
默认 ReentrantLock() 是非公平锁,即新线程会直接尝试抢锁(CAS),失败才进队列。而公平锁强制所有线程严格按 FIFO 进入同步队列:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 构造时传
true:new ReentrantLock(true); - 每次
tryAcquire前,先检查 AQS 队列是否为空,或当前线程是否排在队首; - 不满足条件就直接返回 false,进入
acquireQueued等待,不给“插队”机会。
公平锁降低饥饿概率,但吞吐量通常略低于非公平锁——因为频繁检查队列状态、减少 CAS 尝试次数,增加了调度开销。
组合使用:显式控制 + 安全释放
可重入与公平性可以同时启用,但必须注意资源管理规范:
- 必须配对使用
lock()和unlock(),且unlock()一定要放在finally块中; - 不要跨方法传递锁对象或混用不同锁实例,否则计数器和持有者信息无法匹配;
- 若需响应中断,改用
lockInterruptibly();若需超时,用tryLock(long, TimeUnit); - 避免在持有锁期间执行 I/O、远程调用等长耗时操作,防止拖慢整个队列。
对比 synchronized:灵活性与责任并存
synchronized 自动实现可重入、不可中断、非公平,且无需手动释放;ReentrantLock 则把控制权交还给开发者:
- 优势:支持公平策略、可中断等待、超时获取、多个条件变量(
Condition); - 代价:必须显式释放,遗漏会导致死锁;锁对象本身也参与内存可见性控制,需配合
volatile或正确同步范围使用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










