reentrantlock 获取锁流程本质是 aqs 的独占式同步操作:先通过 state 判断锁状态,非公平模式先 cas 尝试获取,失败则封装为 node 入队;线程自旋检查后阻塞,唤醒后重新竞争;成功后更新 state 并绑定线程,实现可重入。

ReentrantLock 的获取锁流程,本质上是 AQS(AbstractQueuedSynchronizer)框架的一次完整独占式同步操作。它不是简单地“抢一次锁”,而是一套有状态、有队列、有竞争响应的生命周期过程。
state 状态变更:锁是否可用的唯一判断依据
AQS 用一个 volatile int state 字段表示锁的持有状态。ReentrantLock 中:
- state = 0 表示锁空闲,无人持有;
- state > 0 表示已被某线程持有,数值即为该线程的重入次数;
- 获取锁时,非公平模式会先尝试 CAS 将 state 从 0 改为 1;成功则直接设置持有线程并返回;失败则进入排队逻辑;
- 公平模式跳过这步 CAS,直接走排队流程,确保先到先得。
线程入队与节点封装:等待者的组织方式
当线程抢锁失败,AQS 会把它包装成一个 Node 节点,加入同步队列(Sync Queue),这是一个 FIFO 的双向链表:
- 每个 Node 包含线程引用、等待状态(如 SIGNAL、CANCELLED)、前后指针;
- 新节点总插入队尾,前驱节点负责唤醒它(比如前驱释放锁后,会唤醒后继);
- 若线程在排队中被中断或超时,可主动取消节点(置为 CANCELLED),AQS 会在后续清理这些无效节点。
自旋 + 阻塞:等待期间的执行策略
入队后线程不会立刻挂起,而是经历一个轻量级自旋检查:
- 检查前驱节点是否为 head,且自身是否已成为 head.next;
- 满足条件才尝试再次 CAS 获取锁(避免无谓阻塞);
- 若仍失败,才调用 LockSupport.park() 挂起线程,真正进入阻塞态;
- 被唤醒后,会重新参与锁竞争,而非直接获得锁——这是 AQS 的“唤醒即竞争”设计。
成功获取后的状态维护:可重入性的实现基础
一旦线程成功获取锁(无论首次还是重入),AQS 会:
- 更新 state 值(+1);
- 记录当前线程为 exclusiveOwnerThread;
- 后续同一线程再次 lock() 时,只需校验 owner 是否为自己,然后直接 state++,不进队也不阻塞;
- 这种线程绑定 + 计数机制,就是“可重入”的底层保障。
整个流程闭环清晰:从 state 判断开始,经节点入队、自旋/阻塞等待,再到唤醒后重试、最终 state 更新与线程绑定——每一步都由 AQS 统一调度,ReentrantLock 只需专注语义定义。不复杂但容易忽略细节。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











