源码:java.util.concurrent.locks.AbstractQueuedSynchronizer 源码解析

1. TODO


2. 脑图

  1. Xmind

  2. Edraw

  3. Hexo 地址
    👉 http://blog.wangjia.ink/2025/09/01/源码:java.util.concurrent.locks.AbstractQueuedSynchronizer源码解析/


3. 基础部分

3.1. AbstractQueuedSynchronizer 概述

AbstractQueuedSynchronizer 是一个抽象类,继承了 java.util.concurrent.locks.AbstractOwnableSynchronizer,实现了 java.io.Serializable

[!NOTE] 注意事项

  1. 详见源码:AbstractOwnableSynchronizer
    1. obsidian 内部链接:
      1. 源码:java.util.concurrent.locks.AbstractOwnableSynchronizer源码解析
    2. Hexo 链接:
      1. http://blog.wangjia.ink/2025/09/02/源码:java.util.concurrent.locks.AbstractOwnableSynchronizer源码解析/
  2. 详见源码:Serializable
    1. obsidian 内部链接:
      1. 源码:java.io.Serializable源码解析
    2. Hexo 链接:
      1. http://blog.wangjia.ink/2025/10/28/源码:java.io.Serializable源码解析/
  3. 需要注意的是:
    1. Java8AQS 是只有 Node 的,没有 ExclusiveNodeSharedNodeConditionNode

3.2. AbstractQueuedSynchronizer 应用场景

3.2.1. 同步器

同步器是一种协调多个线程执行的工具。它通过内部维护的状态(State),用于控制多个线程对一个或多个共享资源的访问,从而实现线程间的同步与协作

简单来说,多个线程需要先竞争同步器资源(即 State),只有竞争成功的线程才能访问共享资源。而 AQS 提供了一系列机制,使得多个线程能够 “高效且安全” 地竞争、释放 State

在基于 AQS 的同步器实现中,通常需要维护两种队列:

  1. 一条同步队列
    1. 同步队列用于管理那些尝试获取同步器资源,但暂时失败并暂时进入阻塞(WAITINGTIMED_WAITING)的线程
    2. AQS 已经封装好了相关的节点类型(即 NodeExclusiveNodeSharedNode),并且提供了首尾哨兵节点。因此,我们的 AQS 实现类只需要在此基础上维护同步队列即可
  2. 多条条件队列
    1. 条件队列用于管理那些已经获取同步器资源,但因业务条件不满足,而调用了 Condition.await,释放同步器资源并暂时进入阻塞(WAITINGTIMED_WAITING)的线程
    2. AQS 已经封装好了 ConditionObject 和相关的节点类型(即 ConditionNode),一个 ConditionObject 实例就是一条条件队列。因此,我们的 AQS 实现类只需要根据自己的需要,创建并维护 ConditionObject 实例即可

在不同的同步器实现中,State 和共享资源有不同的含义,例如在 ReentrantLock 中:

  1. State 表示锁的重入次数
    1. 0
      1. 表示锁空闲,线程可以尝试获取
    2. 1
      1. 表示锁已被某个线程持有
    3. n(n > 1)
      1. 表示同一线程对该锁进行了 n 次重入
  2. 共享资源表示加锁期间的操作

在使用 AQS 时,绝大多数情况下(约 99%)都是用来实现各种同步器(例如 ReentrantLockSemaphoreCountDownLatch)。在这种情况下,我们可能需要使用到的以下内容:

  1. AOS
    1. 如果基于 AQS 实现的是独占模式的同步器(例如 ReentrantLock),就需要使用 AOS 记录当前独占该资源的线程
    2. 但是如果基于 AQS 实现的是共享模式的同步器(例如 Semaphore),那么 AOS 根本就用不到
  2. AQS
    1. State
    2. 同步队列
    3. 条件队列

在使用 AQS 实现同步器时,通常的做法是:在同步器内部定义一个静态内部类(一般命名为 Sync),并让 Sync 继承 AbstractQueuedSynchronizer,而不是让同步器直接继承 AQS

当外部调用同步器的方法时,执行的流程大致为:外部调用同步器的方法 → 同步器调用 Sync 的方法 → Sync 调用 AQS 的方法

[!NOTE] 注意事项

  1. 猴哥的烦恼箱 (。•́︿•̀。)
    1. 在使用 AQS 实现同步器时,为什么不直接让同步器直接继承 AQS
      1. 其实这里实际使用了 GOF 设计模式之策略模式,以 ReentrangLock 为例
      2. RenntrantLock 需要支持 “公平锁” 和 “非公平锁” 两种模式,而两者在竞争 State 的逻辑上完全不同
      3. 但是 AQS 只提供了竞争 State 的方法,因此具体的竞争逻辑必须由 AQS 的实现类来定义。
      4. 如果同步器直接继承 AQS,就需要在每次操作中使用 if...else if...elseswitch...case...default 判断公平锁或非公平锁,然后执行不同的竞争逻辑
      5. 为了避免大量的 if...else if...elseswitch...case...default 判断,ReentrantLock 就采用了策略模式
      6. ReentrantLock 内部定义了两个静态内部类(即 FairSyncNonFairSync),这两个类分别实现各自的竞争逻辑

3.2.2. 状态机

状态机通过内部维护的状态(State),用于表示其实例在生命周期中可能经历的各个阶段

在使用 AQS 时,有少数情况(约 1%)会用来实现状态机(例如 ThreadPoolExecutor.Worker)。在这种情况下,我们可能需要使用到以下内容:

  1. AQS
    1. State

在不同的状态机实现中,State 有不同的含义,例如在 ThreadPoolExecutor.Worker 中:

  1. -1
    1. Worker 正在被实例化
  2. 0
    1. Worker 并没有 “执行” 任务(正在从任务队列中获取任务)
  3. 1
    1. Worker 正在 “执行” 任务

在使用 AQS 实现状态机时,通常的做法是:直接让状态机继承 AQS

[!NOTE] 注意事项

  1. 猴哥的烦恼箱 (。•́︿•̀。)
    1. 为什么实现状态机还要使用 AQS?我们直接在状态机内部维护一个 State 不就行了嘛?
      1. 因为 AQS 提供了一系列机制,使得多个线程能够 “高效且安全” 地竞争、释放 State
      2. 而我们自己实现不一定能做到这么稳妥,而且只是在走 “AQS” 的老路,不如直接复用最省心

4. 内部类

4.1. Node

详见源码:AbstractQueuedSynchronizer.Node

  1. obsidian 内部链接:
    1. 源码:java.util.concurrent.locks.AbstractQueuedSynchronizer.Node源码解析
  2. Hexo 链接:
    1. http://blog.wangjia.ink/2025/08/31/源码:java.util.concurrent.locks.AbstractQueuedSynchronizer.Node源码解析/

4.2. ExclusiveNode

AbstractQueuedSynchronizer.ExclusiveNode 只是简单地继承了 AbstractQueuedSynchronizer.Node,为 AbstractQueuedSynchronizer.Node 增加了一层 “独占模式节点” 的标签,用来明确区分节点所处的语义

1
static final class ExclusiveNode extends Node { }

[!NOTE] 注意事项

  1. 如果基于 AQS 实现的是独占模式同步器(例如 ReentrantLock),那么同步队列中的 Node 就应该是 ExclusiveNode

4.3. SharedNode

AbstractQueuedSynchronizer.SharedNode 也只是简单地继承了 AbstractQueuedSynchronizer.Node,为 AbstractQueuedSynchronizer.Node 增加了一层 “共享模式节点” 的标签,用来明确区分节点所处的语义

1
static final class SharedNode extends Node { }

[!NOTE] 注意事项

  1. 如果基于 AQS 实现的是共享模式同步器(例如 Semaphore),那么同步队列中的 Node 就应该是 SharedNode

4.4. ConditionObject

详见源码:AbstractQueuedSynchronizer.ConditionObject

  1. obsidian 内部链接:
    1. 源码:java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject源码解析
  2. Hexo 链接:
    1. http://blog.wangjia.ink/2025/08/31/源码:java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject源码解析/

4.5. ConditionNode

详见源码:AbstractQueuedSynchronizer.ConditionNode

  1. obsidian 内部链接:
    1. 源码:java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionNode源码解析
  2. Hexo 链接:
    1. http://blog.wangjia.ink/2025/08/31/源码:java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionNode源码解析/

5. 核心属性

1
2
3
4
5
6
7
8
// 表示 AQS 的同步队列的首哨兵节点
private transient volatile Node head;

// 表示 AQS 的同步队列的尾哨兵节点
private transient volatile Node tail;

// 表示 AQS 的核心状态位(State)
private volatile int state;


源码:java.util.concurrent.locks.AbstractQueuedSynchronizer 源码解析
https://wangjia5289.github.io/2025/09/01/源码:java.util.concurrent.locks.AbstractQueuedSynchronizer源码解析/
Author
咸阳猴🐒
Posted on
September 1, 2025
Licensed under