AQS(AbstractQueuedSynchronizer)抽象队列同步器

一、AQS 是什么?

AQS (AbstractQueuedSynchronizer) 是一个抽象类,位于 java.util.concurrent.locks 包下。它为构建锁(Locks)同步器(Synchronizers) 提供了一个框架

简单来说,AQS 就是一个“并发工具制造工厂”的核心引擎。JUC 包中几乎所有重要的同步工具,其底层实现都依赖于 AQS。

它的主要思想是:

  1. 状态管理: 使用一个 int 类型的成员变量 state 来表示同步状态(如:锁是否被占用、剩余许可证数量、倒计时数值等)。
  2. 队列管理: 内部维护一个FIFO 的双向队列(CLH 队列的变种),用于管理等待获取共享资源的线程。当线程获取资源失败时,会被封装成一个节点(Node)加入队列并阻塞;当资源可用时,按 FIFO 顺序唤醒队列中的线程。
  3. 模板方法模式: AQS 本身定义了获取和释放资源的主流程(如 acquirereleaseacquireSharedreleaseShared),但将如何判断状态、如何修改状态的具体逻辑(即 tryAcquiretryReleasetryAcquireSharedtryReleaseShared 等方法)留给子类去实现。这是一种典型的模板方法设计模式。

二、AQS 与前面提到的锁和同步器的关系

核心关系:AQS 是这些并发工具的底层实现基础。

我们可以把 AQS 想象成一个“发动机”,而 ReentrantLockCountDownLatch 等就是装上了不同“外壳”和“控制面板”的“汽车”或“机器”。它们共享同一个核心动力系统(AQS),但对外提供的功能和接口不同。

下面具体说明:

2.1 AQS 与 ReentrantLock

  • 关系: ReentrantLock 的核心实现类 ReentrantLock.Sync(及其子类 NonfairSync 和 FairSync直接继承自 AQS
  • 如何工作:
    • state 变量表示锁的重入次数。0 表示锁未被占用,大于 0 表示锁已被占用,数值即为重入次数。
    • tryAcquire(int acquires):子类实现。尝试获取锁。如果是非公平锁,会直接尝试 CAS 修改 state;如果是公平锁,会先检查队列中是否有等待线程。如果当前线程已持有锁,则增加 state(重入)。
    • tryRelease(int releases):子类实现。释放锁,减少 state。如果 state 减到 0,表示锁完全释放,返回 true,AQS 会唤醒队列中的下一个线程。
    • lock() 方法最终会调用 AQS 的 acquire(1) 方法。
    • unlock() 方法最终会调用 AQS 的 release(1) 方法。
  • 总结: ReentrantLock 的所有核心逻辑(排队、阻塞、唤醒、重入)都是由 AQS 提供的框架来完成的,它只需要实现“如何判断和修改锁状态”这个核心逻辑。

2.2 AQS 与 ReentrantReadWriteLock

  • 关系: ReentrantReadWriteLock 的核心实现类 ReentrantReadWriteLock.Sync 也继承自 AQS
  • 如何工作:
    • state 变量被按位拆分使用。高 16 位表示读锁的重入次数,低 16 位表示写锁的重入次数。
    • tryAcquire(int acquires):实现写锁的获取逻辑(独占模式)。
    • tryAcquireShared(int acquires):实现读锁的获取逻辑(共享模式)。只要没有写锁或只有当前线程持有写锁,就可以获取读锁。
    • tryRelease(int releases):释放写锁。
    • tryReleaseShared(int releases):释放读锁。
  • 总结: 读写锁的复杂状态管理(读读共享、读写互斥、写写互斥、重入)都是在 AQS 的框架下,通过巧妙地操作 state 的高低位来实现的。

2.3 AQS 与 CountDownLatch

  • 关系: CountDownLatch 的内部类 Sync 继承自 AQS
  • 如何工作:
    • state 变量直接表示倒计时的数值(即构造函数传入的 count)。
    • tryAcquireShared(int acquires):实现 await() 的逻辑。如果 state == 0,返回 1(表示获取成功,线程可以继续);否则返回 -1(表示获取失败,线程需要入队等待)。
    • tryReleaseShared(int releases):实现 countDown() 的逻辑。通过 CAS 将 state 减 1。如果减到 0,返回 true,AQS 会唤醒所有在 await() 中等待的线程(因为是共享模式)。
  • 总结: CountDownLatch 的“等待计数器归零”的核心功能,完全是由 AQS 的共享模式(acquireShared / releaseShared)来驱动的。countDown() 调用 releaseSharedawait() 调用 acquireShared

2.4 AQS 与 Semaphore

  • 关系: Semaphore 的内部类 Sync(及其子类 NonfairSync 和 FairSync继承自 AQS
  • 如何工作:
    • state 变量表示剩余的许可证(permits)数量
    • tryAcquireShared(int acquires):尝试获取指定数量的许可证。如果剩余数量足够,则 CAS 减少 state 并返回正数(成功);否则返回负数(失败,入队等待)。
    • tryReleaseShared(int releases):释放指定数量的许可证,增加 state,并可能唤醒等待的线程。
  • 总结: 信号量的“控制并发访问数量”的功能,是通过 AQS 的共享模式和 state 作为许可证计数器来实现的。

2.5 AQS 与 其他工具

  • FutureTask: 也使用了 AQS 来管理任务的执行状态(未开始、运行中、已完成/取消)和等待获取结果的线程。
  • CyclicBarrier: 虽然 CyclicBarrier 本身没有直接继承 AQS,但它内部是通过 ReentrantLock 和 Condition 来实现的,而 ReentrantLock 底层就是 AQS。所以它间接依赖 AQS。
  • StampedLock: StampedLock 没有使用 AQS!它使用了更底层的 UNSAFE 操作和复杂的 CLH 队列变种来实现,以追求更高的性能。这是它的一个重要特点。

三、AQS 的两种模式

AQS 定义了两种资源共享方式,子类必须实现相应的方法:

  1. Exclusive (独占模式):

    • 只有一个线程能执行,如 ReentrantLock
    • 子类需要实现:tryAcquire(int)tryRelease(int)
    • 对外调用:acquire(int)release(int)
  2. Share (共享模式):

    • 多个线程可同时执行,如 Semaphore / CountDownLatch / ReentrantReadWriteLock 的读锁。
    • 子类需要实现:tryAcquireShared(int)tryReleaseShared(int)
    • 对外调用:acquireShared(int)releaseShared(int)

一个同步器可以同时实现两种模式,比如 ReentrantReadWriteLock


四、为什么 AQS 如此重要?

  1. 统一框架: 为各种不同的同步需求(互斥、共享、计数、信号量)提供了一个统一、高效、可靠的底层实现框架。开发者无需从头实现复杂的线程排队、阻塞、唤醒逻辑。
  2. 高性能: AQS 的队列管理、CAS 操作、线程阻塞/唤醒机制都经过了高度优化。
  3. 可靠性: 作为 JDK 的核心组件,经过了无数生产环境的考验。
  4. 可扩展性: 通过模板方法模式,开发者可以基于 AQS 轻松地创建自己定制的同步组件(虽然大部分情况下 JUC 提供的工具已经足够)。

五、总结:AQS 的“家族树”

                          AbstractQueuedSynchronizer (AQS)
                                   /       |       \
                                  /        |        \
                                 /         |         \
                                /          |          \
                               /           |           \
                              /            |            \
                             /             |             \
             (独占模式实现)  /              | (共享模式实现) \
                           /               |               \
                          /                |                \
                         /                 |                 \
                        /                  |                  \
                       /                   |                   \
                      /                    |                    \
                     /                     |                     \
                    /                      |                      \
                   /                       |                       \
                  /                        |                        \
                 /                         |                         \
                /                          |                          \
               /                           |                           \
              /                            |                            \
ReentrantLock.Sync           ReentrantReadWriteLock.Sync       CountDownLatch.Sync        Semaphore.Sync
 (Fair/Nonfair)              (Fair/Nonfair, manages read/write)   (manages count)         (Fair/Nonfair, manages permits)

简单来说:

  • ReentrantLockReentrantReadWriteLockCountDownLatchSemaphore 这些你熟悉的并发工具,它们的“心脏”都是 AQS
  • 它们通过继承 AQS 并实现特定的 tryXXX 方法,来定义自己独特的同步语义(锁、读写锁、倒计时、许可证)。
  • AQS 负责处理所有复杂的、通用的线程排队、阻塞、唤醒、状态管理的底层细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值