AQS同步器核心原理深度剖析

AQS同步器核心原理深度剖析

前言

AQS(AbstractQueuedSynchronizer)是Java并发包java.util.concurrent的核心基础组件,它是实现锁、信号量、倒计时门栓、循环屏障等同步器的基础。理解AQS的原理,对于深入掌握Java并发编程、阅读JUC源码、甚至自定义同步器都至关重要。本文将从设计思想、核心数据结构、源码实现三个维度全面解析AQS。

一、AQS概述

1.1 什么是AQS

AQS是Java并发编程中用于构建锁和同步器的框架。它使用一个int类型的state变量表示同步状态,并通过一个FIFO双向队列管理获取锁失败的线程。

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                      AQS 架构图                                  │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │              AbstractQueuedSynchronizer                │   │
│  │                                                          │   │
│  │  ┌────────────────┐    ┌──────────────────────────────┐ │   │
│  │  │   state (int)  │    │     CLH队列 (FIFO)          │ │   │
│  │  │   同步状态       │    │  ┌────┐┌────┐┌────┐┌────┐  │ │   │
│  │  │                 │    │  │T1  ││T2  ││T3  ││T4  │  │ │   │
│  │  │  getState()     │    │  └────┘└────┘└────┘└────┘  │ │   │
│  │  │  setState()     │    │  ◄──── 队列方向 ────►      │ │   │
│  │  │  compareAndSet()│    │                             │ │   │
│  │  └────────────────┘    └──────────────────────────────┘ │   │
│  └──────────────────────────────────────────────────────────┘   │
│                            │                                     │
│              ┌─────────────┴─────────────┐                       │
│              │                           │                       │
│              ▼                           ▼                       │
│  ┌───────────────────────┐     ┌───────────────────────┐        │
│  │   ReentrantLock       │     │   Semaphore          │        │
│  │   (可重入锁)          │     │   (信号量)            │        │
│  └───────────────────────┘     └───────────────────────┘        │
│                                                                 │
│  ┌───────────────────────┐     ┌───────────────────────┐        │
│  │   CountDownLatch      │     │   ReentrantReadWrite │        │
│  │   (倒计时门栓)          │     │   Lock (读写锁)       │        │
│  └───────────────────────┘     └───────────────────────┘        │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

1.2 AQS的设计思想

复制代码
/**
 * AQS核心设计模式:模板方法
 * 
 * AQS定义了同步器的基本骨架,子类只需要实现特定方法
 * 就可以自定义同步行为
 */

public abstract class AbstractQueuedSynchronizer 
        extends AbstractOwnableSynchronizer 
        implements java.io.Serializable {

    // 需要子类实现的方法(尝试获取同步状态)
    protected abstract boolean tryAcquire(int arg);

    // 需要子类实现的方法(尝试释放同步状态)
    protected abstract boolean tryRelease(int arg);

    // 需要子类实现的方法(判断是否处于锁定状态)
    protected abstract boolean isHeldExclusively();

    // AQS提供的模板方法(使用tryAcquire)
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

    // AQS提供的模板方法(使用tryRelease)
    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }
}

二、核心数据结构

2.1 CLH队列节点

复制代码
// Node是CLH队列中的节点
static final class Node {
    // 模式标记
    static final Node EXCLUSIVE = null;      // 独占模式
    static final Node SHARED = new Node();    // 共享模式

    // 等待状态
    static final int CANCELLED =  1;         // 取消状态
    static final int SIGNAL    = -1;         // 需要唤醒后继节点
    static final int CONDITION = -2;         // 等待条件
    static final int PROPAGATE = -3;         // 传播状态

    // 等待状态(volatile)
    volatile int waitStatus;

    // 前驱节点
    volatile Node prev;

    // 后继节点
    volatile Node next;

    // 当前节点代表的线程
    volatile Thread thread;

    // 下一个等待节点(用于Condition队列)
    Node nextWaiter;

    // ...
}

2.2 队列结构图

复制代码
CLH队列结构:

          Head                    Tail
          ┌────┐                  ┌────┐
          │Node│◄────────────────►│Node│
          │null│   (prev)  (next) │    │
          │null│                  │ T4 │
          └┬───┘                  └─┬──┘
           │                        │
           │                        ▼
           │                 ┌────────────┐
           │                 │   prev     │◄────────┐
           │                 │            │          │
           │                 │   thread   │ (T4)     │
           │                 │            │          │
           │                 │   next     │─────┐    │
           │                 └────────────┘     │    │
           │                                   │    │
           ▼                                   │    │
     ┌───────────┐                             │    │
     │           │                             │    │
     │   (空)    │  ◄── Head节点               │    │
     │           │      不持有线程              │    │
     └───────────┘                             │    │
                                               │    │
          ┌────────────┐                       │    │
          │   prev     │───────────────────────┘    │
          │            │                             │
          │   thread   │ (T1)                       │
          │            │                             │
          │   next     │────►┌────────────┐         │
          └────────────┘     │   prev     │◄────────┘
                             │            │
                             │   thread   │ (T2)
                             │            │
                             │   next     │────► ...
                             └────────────┘

2.3 state状态管理

复制代码
/**
 * 同步状态state的语义由子类定义
 * 
 * ReentrantLock: state表示重入次数(0表示未被持有)
 * Semaphore: state表示剩余许可数
 * CountDownLatch: state表示计数器值
 * ReentrantReadWriteLock: 高16位读锁计数,低16位写锁计数
 */

public abstract class AbstractQueuedSynchronizer 
        extends AbstractOwnableSynchronizer {

    // 同步状态 - 使用volatile保证可见性
    private volatile int state;

    // 获取状态
    protected final int getState() {
        return state;
    }

    // 设置状态
    protected final void setState(int newState) {
        state = newState;
    }

    // CAS设置状态(JDK推荐的方式)
    protected final boolean compareAndSetState(int expect, int update) {
        return U.compareAndSwapInt(this, STATE, expect, update);
    }
}

三、独占模式源码解析

3.1 acquire流程

复制代码
/**
 * acquire - 独占模式获取同步状态
 * 
 * 流程:
 * 1. tryAcquire尝试获取
 * 2. 获取成功,直接返回
 * 3. 获取失败,加入等待队列
 * 4. 在队列中自旋等待
 * 5. 被唤醒后尝试获取
 */
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        // 如果被中断唤醒,恢复中断状态
        selfInterrupt();
}

/**
 * addWaiter - 创建节点并加入队列
 */
private Node addWaiter(Node mode) {
    Node node = new Node(Thread.currentThread(), mode);

    // 先尝试快速入队(乐观方式)
    Node pred = tail;
    if (pred != null) {
        node.prev = pred;
        if (compareAndSetTail(pred, node)) {
            pred.next = node;
            return node;
        }
    }

    // 快速入队失败,使用完整入队
    enq(node);
    return node;
}

/**
 * enq - 完整入队(包含初始化队列)
 */
private Node enq(Node node) {
    for (;;) {
        Node t = tail;
        if (t == null) {
            // 队列为空,需要初始化
            if (compareAndSetHead(new Node()))
                tail = head;
        } else {
            // 正常入队
            node.prev = t;
            if (compareAndSetTail(t, node)) {
                t.next = node;
                return t;
            }
        }
    }
}

/**
 * acquireQueued - 在队列中自旋获取
 */
final boolean acquireQueued(final Node node, int arg) {
    boolean failed = true;
    try {
        boolean interrupted = false;
        for (;;) {
            // 获取前驱节点
            final Node p = node.predecessor();

            // 如果前驱是头节点,尝试获取
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null;  // 帮助GC
                failed = false;
                return interrupted;
            }

            // 检查是否需要阻塞
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())
                interrupted = true;
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

/**
 * shouldParkAfterFailedAcquire - 检查是否应该阻塞
 * 
 * 只有当前驱节点状态为SIGNAL时才阻塞
 * 否则向前传播或重置状态
 */
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
    int ws = pred.waitStatus;

    // 前驱节点会唤醒后继节点
    if (ws == Node.SIGNAL)
        return true;

    // 前驱节点已取消,跳过
    if (ws > 0) {
        do {
            node.prev = pred = pred.prev;
        } while (pred.waitStatus > 0);
        pred.next = node;
    } else {
        // 设置前驱节点为SIGNAL
        compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
    }
    return false;
}

3.2 release流程

复制代码
/**
 * release - 独占模式释放同步状态
 */
public final boolean release(int arg) {
    if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}

/**
 * unparkSuccessor - 唤醒后继节点
 */
private void unparkSuccessor(Node node) {
    int ws = node.waitStatus;

    // 重置头节点状态
    if (ws < 0)
        compareAndSetWaitStatus(node, ws, 0);

    Node s = node.next;

    // 从后向前找最接近的未取消节点
    if (s == null || s.waitStatus > 0) {
        s = null;
        for (Node t = tail; t != null && t != node; t = t.prev)
            if (t.waitStatus <= 0)
                s = t;
    }

    // 唤醒节点
    if (s != null)
        LockSupport.unpark(s.thread);
}

3.3 等待队列操作图解

复制代码
场景:4个线程获取锁,线程1持有锁

初始状态(线程1持有锁):
┌────────────────────────────────────────────────────┐
│  ┌──────┐      ┌──────┐  ┌──────┐  ┌──────┐      │
│  │ HEAD │◄────►│ T2   │◄►│ T3   │◄►│ TAIL │      │
│  │ null │      │ wait │  │ wait │  │      │      │
│  │ SIGNAL│     │ -1   │  │ -1   │  │      │      │
│  └──────┘      └──────┘  └──────┘  └──────┘      │
│      │                                         │
│      │ Lock held by T1                          │
│      ▼                                          │
│  ┌──────┐                                       │
│  │ T1   │ (当前持有锁)                           │
│  │      │                                       │
│  └──────┘                                       │
└────────────────────────────────────────────────────┘

线程1释放锁,唤醒线程2:
┌────────────────────────────────────────────────────┐
│  ┌──────┐      ┌──────┐  ┌──────┐                  │
│  │ HEAD │◄────►│ T3   │◄►│ TAIL │                  │
│  │ null │      │ wait │  │      │                  │
│  │ 0    │      │ -1   │  │      │                  │
│  └──────┘      └──────┘  └──────┘                  │
│      │                                            │
│      │ T1 released, unpark(T2)                    │
│      │ T2 wakes up, acquires lock                  │
│      ▼                                            │
│  ┌──────┐                                          │
│  │ T2   │ (now head, holds lock)                   │
│  │      │                                          │
│  └──────┘                                          │
└────────────────────────────────────────────────────┘

T2 head状态(锁被T2持有):
┌────────────────────────────────────────────────────┐
│  ┌──────┐      ┌──────┐                           │
│  │ T2   │◄────►│ T3   │ (TAIL)                    │
│  │      │      │ wait │                           │
│  │ -1   │      │ -1   │                           │
│  └──────┘      └──────┘                           │
│      │                                            │
│      │ Lock held by T2                            │
│      ▼                                            │
│  ┌──────────────────────────────────────────┐    │
│  │ T2 executing critical section             │    │
│  └──────────────────────────────────────────┘    │
└────────────────────────────────────────────────────┘

四、共享模式源码解析

4.1 acquireShared流程

复制代码
/**
 * acquireShared - 共享模式获取同步状态
 * 
 * 共享模式允许多个线程同时持有同步状态
 * 例如:Semaphore信号量、ReadWriteLock读锁
 */
public final void acquireShared(int arg) {
    if (tryAcquireShared(arg) < 0)  // < 0 表示获取失败
        doAcquireShared(arg);
}

/**
 * doAcquireShared - 在队列中自旋获取(共享模式)
 */
private void doAcquireShared(int arg) {
    // 添加SHARED模式的节点
    final Node node = addWaiter(Node.SHARED);
    boolean failed = true;
    try {
        boolean interrupted = false;
        for (;;) {
            final Node p = node.predecessor();
            if (p == head) {
                // 前驱是头节点,尝试获取
                int r = tryAcquireShared(arg);
                if (r >= 0) {
                    // 获取成功,需要传播给后继节点
                    setHeadAndPropagate(node, r);
                    p.next = null;  // help GC
                    failed = false;
                    return;
                }
            }
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())
                interrupted = true;
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

/**
 * setHeadAndPropagate - 设置头节点并传播
 */
private void setHeadAndPropagate(Node node, int propagate) {
    Node h = head;
    setHead(node);

    // 传播:唤醒后继共享节点
    if (propagate > 0 || h == null || h.waitStatus < 0 ||
        (h = head) == null || h.waitStatus < 0) {
        Node s = node.next;
        if (s == null || s.isShared())
            doReleaseShared();
    }
}

4.2 releaseShared流程

复制代码
/**
 * releaseShared - 共享模式释放同步状态
 */
public final boolean releaseShared(int arg) {
    if (tryReleaseShared(arg)) {
        doReleaseShared();
        return true;
    }
    return false;
}

/**
 * doReleaseShared - 唤醒后继节点(共享模式)
 */
private void doReleaseShared() {
    for (;;) {
        Node h = head;
        if (h != null && h != tail) {
            int ws = h.waitStatus;

            if (ws == Node.SIGNAL) {
                // 唤醒后继节点
                if (compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                    unparkSuccessor(h);
            }
            else if (ws == 0 &&
                     !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)))
                continue;  // 重试
        }

        if (h == head)  // 如果头节点没变,退出
            break;
    }
}

五、自定义同步器实现

5.1Mutex(互斥锁)实现

复制代码
/**
 * 自定义互斥锁 - 基于AQS实现
 */
public class Mutex implements Lock {

    // 内部Sync类
    private static class Sync extends AbstractQueuedSynchronizer {

        // 判断是否被占用
        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

        // 尝试获取锁(独占模式)
        @Override
        protected boolean tryAcquire(int acquires) {
            // CAS设置状态为1
            if (compareAndSetState(0, 1)) {
                // 设置持有锁的线程
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        // 尝试释放锁
        @Override
        protected boolean tryRelease(int releases) {
            if (getState() == 0)
                throw new IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        // 创建ConditionObject
        Condition newCondition() {
            return new ConditionObject();
        }
    }

    private final Sync sync = new Sync();

    @Override
    public void lock() {
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }
}

// 使用示例
public class MutexDemo {
    private final Mutex mutex = new Mutex();

    public void doSomething() {
        mutex.lock();
        try {
            // 临界区操作
        } finally {
            mutex.unlock();
        }
    }
}

5.2 Semaphore(信号量)实现

复制代码
/**
 * 自定义信号量 - 基于AQS实现
 */
public class CustomSemaphore {

    private static final class Sync extends AbstractQueuedSynchronizer {

        private final int permits;

        Sync(int permits) {
            this.permits = permits;
            setState(permits);
        }

        // 共享模式获取
        @Override
        protected int tryAcquireShared(int acquires) {
            for (;;) {
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }

        // 共享模式释放
        @Override
        protected boolean tryReleaseShared(int releases) {
            for (;;) {
                int current = getState();
                int next = current + releases;
                if (compareAndSetState(current, next))
                    return true;
            }
        }
    }

    private final Sync sync;

    public CustomSemaphore(int permits) {
        sync = new Sync(permits);
    }

    public void acquire() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    public void release() {
        sync.releaseShared(1);
    }

    public int availablePermits() {
        return sync.getState();
    }
}

5.3 CountDownLatch(倒计时门栓)实现

复制代码
/**
 * 自定义倒计时门栓 - 基于AQS实现
 */
public class CustomCountDownLatch {

    private static final class Sync extends AbstractQueuedSynchronizer {

        Sync(int count) {
            setState(count);
        }

        // 共享模式获取(倒计时到0时才成功)
        @Override
        protected int tryAcquireShared(int acquires) {
            return getState() == 0 ? 1 : -1;
        }

        // 共享模式释放(计数器-1)
        @Override
        protected boolean tryReleaseShared(int releases) {
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;  // 已经是0,无法再释放
                int nextc = c - 1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;  // 只有减到0才返回true
            }
        }
    }

    private final Sync sync;

    public CustomCountDownLatch(int count) {
        if (count < 0)
            throw new IllegalArgumentException("count < 0");
        sync = new Sync(count);
    }

    // 等待计数器归零
    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    // 计数器-1
    public void countDown() {
        sync.releaseShared(1);
    }

    // 获取当前计数器值
    public long getCount() {
        return sync.getState();
    }
}

// 使用示例
public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CustomCountDownLatch latch = new CustomCountDownLatch(3);

        // 启动3个线程
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                try {
                    Thread.sleep(1000);
                    System.out.println("任务完成");
                    latch.countDown();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
        }

        // 等待所有任务完成
        latch.await();
        System.out.println("所有任务已完成");
    }
}

六、AQS在JUC中的应用

6.1 应用总览

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                     AQS 的应用                                  │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌───────────────────┐   ┌───────────────────────────────────┐ │
│  │    ReentrantLock   │   │     ReentrantReadWriteLock        │ │
│  │                   │   │                                    │ │
│  │  tryAcquire()     │   │  tryAcquireShared() - 读锁         │ │
│  │  tryRelease()     │   │  tryReleaseShared() - 读锁释放     │ │
│  │  isHeldExclusively│   │  tryAcquire() - 写锁                │ │
│  │                   │   │  tryRelease() - 写锁释放          │ │
│  │  state = 重入次数  │   │  state = 高16位读+低16位写         │ │
│  └───────────────────┘   └───────────────────────────────────┘ │
│                                                                 │
│  ┌───────────────────┐   ┌───────────────────────────────────┐ │
│  │    Semaphore      │   │       CountDownLatch               │ │
│  │                   │   │                                    │ │
│  │  tryAcquire()     │   │  tryAcquireShared() - 等待归零    │ │
│  │  tryRelease()     │   │  tryReleaseShared() - 计数-1      │ │
│  │                   │   │                                    │ │
│  │  state = 许可数   │   │  state = 计数器值                  │ │
│  └───────────────────┘   └───────────────────────────────────┘ │
│                                                                 │
│  ┌───────────────────┐   ┌───────────────────────────────────┐ │
│  │  CyclicBarrier     │   │        FutureTask                  │ │
│  │                   │   │                                    │ │
│  │  使用ReentrantLock │   │  使用AQS state管理任务状态         │ │
│  │  + Condition实现   │   │  0=初始化, 1=运行中, 2=已完成      │ │
│  └───────────────────┘   └───────────────────────────────────┘ │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

6.2 ReentrantLock与AQS

复制代码
/**
 * ReentrantLock使用AQS的方式:
 * 
 * 1. 内部有FairSync和NonfairSync两种实现
 * 2. state表示重入次数
 * 3. exclusiveOwnerThread记录持有锁的线程
 */

public class ReentrantLock implements Lock, java.io.Serializable {

    private final Sync sync;

    // 非公平锁
    static final class NonfairSync extends Sync {
        @Override
        protected boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

    // 公平锁
    static final class FairSync extends Sync {
        @Override
        protected boolean tryAcquire(int acquires) {
            Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                // 公平锁:检查是否有等待更久的线程
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            } else if (current == getExclusiveOwnerThread()) {
                // 可重入:累加重入次数
                int nextc = c + acquires;
                setState(nextc);
                return true;
            }
            return false;
        }
    }
}

总结

AQS是Java并发编程的基础设施,理解它需要掌握以下几个核心要点:

  1. 核心思想:模板方法模式,子类只需实现tryAcquire/tryRelease等方法
  2. 数据结构:state变量表示同步状态,CLH队列管理等待线程
  3. 独占模式:同一时刻只有一个线程持有同步状态(ReentrantLock)
  4. 共享模式:多个线程可以同时持有同步状态(Semaphore)
  5. 队列操作:addWaiter入队、shouldParkAfterFailedAcquire判断是否阻塞、unparkSuccessor唤醒
  6. 条件变量:ConditionObject与AQS队列配合实现等待/通知机制

AQS的设计体现了Doug Lea大师对并发控制的深刻理解,是学习Java并发编程不可绕过的重要知识点。

相关推荐
南棱笑笑生2 小时前
20260420给万象奥科的开发板HD-RK3576-PI适配瑞芯微原厂的Buildroot时使用ll命令
java·大数据·elasticsearch·rockchip
StockTV2 小时前
韩国市场API技术对接指南,涵盖实时行情、历史数据、指数信息、公司详情等功能
java·开发语言·python·php
缪懿2 小时前
javaEE:文件IO
java·java-ee
小Y._3 小时前
ConcurrentHashMap高效并发机制深度解析
java·并发·juc·concurrenthashmap
tang_jian_dong3 小时前
springboot + vue3 集成tianai.captcha验证码
java·spring boot·spring
Traving Yu3 小时前
JVM 底层与调优
java·jvm
三棱球3 小时前
Java 基础教程 Day2:从数据类型到面向对象核心概念
java·开发语言
indexsunny3 小时前
互联网大厂Java面试实录:微服务+Spring Boot在电商场景中的应用
java·spring boot·redis·微服务·eureka·kafka·spring security
wuminyu3 小时前
专家视角看Java线程生命周期与上下文切换的本质
java·linux·c语言·jvm·c++