AQS(抽象队列同步器)详解

AQS(AbstractQueuedSynchronizer)详解

AQS(java.util.concurrent.locks.AbstractQueuedSynchronizer)是Java并发包(JUC)的核心基础框架,用于构建锁(如ReentrantLock)和同步器(如SemaphoreCountDownLatch)。它通过 CLH队列(变种的双向链表) 管理线程的阻塞与唤醒,并提供了一套 模板方法,让开发者只需实现少量关键方法即可自定义同步器。


1. AQS 核心思想

AQS 的核心是一个 FIFO 等待队列 和一个 volatile 的 state(同步状态),通过 CAS 操作控制锁的获取与释放:

  • state(int 类型):表示锁的状态(如 ReentrantLock 中,state=0 表示未锁定,state>0 表示被占用)。

  • CLH 队列:存储等待锁的线程,采用 双向链表 结构(FIFO 公平锁)。


2. AQS 关键方法

AQS 采用 模板方法模式,子类只需实现以下方法:

方法名说明
tryAcquire(int arg)尝试获取锁(需子类实现,返回 true 表示成功)
tryRelease(int arg)尝试释放锁(需子类实现,返回 true 表示成功)
tryAcquireShared(int arg)尝试获取共享锁(如 SemaphoreCountDownLatch
tryReleaseShared(int arg)尝试释放共享锁
isHeldExclusively()当前线程是否独占锁(用于 Condition 条件变量)

示例ReentrantLock 的 NonfairSync(非公平锁)实现:

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (compareAndSetState(0, acquires)) { // CAS 尝试获取锁
            setExclusiveOwnerThread(current);  // 设置当前线程为锁持有者
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) { // 可重入逻辑
        int nextc = c + acquires;
        if (nextc < 0) throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

3. AQS 的两种模式

AQS 支持 独占锁(Exclusive) 和 共享锁(Shared)

(1) 独占锁(Exclusive)

  • 一次只有一个线程能获取锁(如 ReentrantLock)。

  • 核心方法

    • acquire(int arg) → 调用 tryAcquire(),失败则加入队列并阻塞。

    • release(int arg) → 调用 tryRelease(),成功后唤醒后续线程。

(2) 共享锁(Shared)

  • 允许多个线程同时获取锁(如 SemaphoreCountDownLatch)。

  • 核心方法

    • acquireShared(int arg) → 调用 tryAcquireShared()

    • releaseShared(int arg) → 调用 tryReleaseShared()


4. AQS 的底层实现

(1) CLH 队列(Craig, Landin, and Hagersten 锁队列)

  • 数据结构:双向链表(Node 节点),每个节点代表一个等待线程。

  • 关键字段

    • waitStatus:线程状态(CANCELLEDSIGNALCONDITION 等)。

    • prevnext:前驱和后继节点。

  • 入队:通过 CAS 操作将新节点加入队尾。

  • 出队:头节点(head)释放锁后,唤醒后继节点。

(2) 自旋与阻塞

  • 非公平锁:直接尝试 CAS 获取锁,失败后再入队(ReentrantLock.NonfairSync)。

  • 公平锁:直接加入队列,严格按 FIFO 获取锁(ReentrantLock.FairSync)。


5. AQS 的应用

AQS 是 JUC 同步器的基础,几乎所有高级锁都基于它实现:

同步器实现方式
ReentrantLock独占锁(支持公平/非公平)
ReentrantReadWriteLock读锁(共享)、写锁(独占)
Semaphore共享锁(控制并发数)
CountDownLatch共享锁(等待所有任务完成)
CyclicBarrier结合 Condition 实现

6. AQS 的优缺点

✅ 优点

  • 灵活性:可自定义独占锁、共享锁、条件变量等。

  • 高性能:通过 CAS 和 CLH 队列减少竞争。

  • 广泛应用:JUC 大部分同步工具基于 AQS。

❌ 缺点

  • 复杂性:需要理解模板方法模式和 CLH 队列。

  • 不适用于所有场景:某些特殊同步需求可能需要更低级别的控制(如 VarHandle)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值