reentrantlock 通过 aqs 的 state(重入计数)和 exclusiveownerthread(持有线程)实现可重入:同一线程重复加锁仅增计数,释放时减至 0 才真正唤醒等待者,公平/非公平模式均不影响该逻辑。

ReentrantLock 通过持有线程标识 + 重入计数实现可重入互斥锁。它不是靠 JVM 隐式支持(如 synchronized),而是用 AQS(AbstractQueuedSynchronizer)作为底层同步框架,自己维护“当前持有线程”和“重入次数”两个核心状态。
核心机制:线程身份识别 + 计数器
每次加锁时,ReentrantLock 会检查当前锁是否已被某个线程持有:
- 如果无人持有,就将当前线程设为持有者,重入计数设为 1;
- 如果当前线程正是持有者,就只将重入计数 +1,不阻塞;
- 如果是其他线程尝试获取,则进入 AQS 队列等待(公平模式)或自旋+CAS 尝试(非公平模式默认)。
释放锁时,仅将重入计数 -1;只有计数减到 0 才真正释放锁,并唤醒等待队列中的下一个线程。
底层依赖 AQS 的 state 和 exclusiveOwnerThread
AQS 提供了三个关键支撑:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- state 字段(volatile int):表示重入次数,初始为 0;
- exclusiveOwnerThread 字段(Thread):记录当前独占锁的线程,null 表示无主;
- CAS 操作(compareAndSetState):保证 state 修改的原子性,避免竞态。
例如 lock() 方法本质是调用 AQS 的 acquire(1),而 tryAcquire(1) 的逻辑就是:先读 exclusiveOwnerThread,匹配则 state+1;不匹配则尝试 CAS 设置 state 从 0→1 并设置 exclusiveOwnerThread 为当前线程。
可重入的典型表现与验证
可重入性体现在同一个线程可多次调用 lock() 而不被自己阻塞,且必须调用相同次数 unlock() 才真正释放:
- 递归调用安全:比如一个加锁方法内部又调用了另一个同样需要该锁的方法;
- lock() 和 unlock() 必须成对:少一次 unlock(),锁不会释放;多一次会抛 IllegalMonitorStateException;
- 可通过 getHoldCount() 查看当前线程的重入次数,isHeldByCurrentThread() 判断是否持有。
公平性与非公平性的差异不影响可重入逻辑
无论构造时传入 true(公平)还是 false(非公平,默认),可重入的判断逻辑完全一致——都基于 exclusiveOwnerThread 和 state。区别仅在于新线程抢锁时是否检查队列是否有等待者:
- 非公平:插队尝试 CAS 获取锁,提升吞吐;
- 公平:直接入队,按顺序唤醒,避免饥饿。
但只要锁已被当前线程持有,两种模式都会直接增加重入计数,跳过排队逻辑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










