AbstractQueuedSynchronizer(AQS)深度解析

一、核心架构设计

1.1 基础数据结构

AQS通过同步状态(state)CLH队列实现线程同步控制:

  • state变量volatile int类型,表示同步状态(如锁重入次数、信号量许可数)
  • 双向链表队列:由Node节点组成,每个节点封装等待线程及状态信息
  • 头尾指针:通过CAS操作维护队列的FIFO特性
// 核心成员变量
private transient volatile Node head;
private transient volatile Node tail;
private volatile int state;

1.2 Node节点结构

static final class Node {
    static final Node SHARED = new Node();
    static final Node EXCLUSIVE = null;
    static final int CANCELLED =  1;
    static final int SIGNAL    = -1;
    static final int CONDITION = -2;
    static final int PROPAGATE = -3;

    volatile int waitStatus;
    volatile Node prev;
    volatile Node next;
    volatile Thread thread;
    Node nextWaiter;
}
  • waitStatus:线程等待状态(5种状态)
  • nextWaiter:区分独占/共享模式(EXCLUSIVE/SHARED)

二、核心工作机制

2.1 独占模式(Exclusive)

2.1.1 获取锁流程

graph TD
    A[调用acquire(arg)] --> B{tryAcquire(arg)}
    B -->|成功| C[设置独占线程]
    B -->|失败| D[addWaiter]
    D --> E[acquireQueued]
    E -->|自旋成功| F[获取锁]
    E -->|阻塞等待| G[LockSupport.park]

2.1.2 关键方法

  • tryAcquire:尝试获取锁(子类实现)
  • addWaiter:将线程封装为Node加入队列尾部
  • acquireQueued:自旋等待并阻塞

2.2 共享模式(Shared)

2.2.1 获取锁流程

graph TD
    A[调用acquireShared(arg)] --> B{tryAcquireShared(arg)}
    B -->|成功| C[传播唤醒]
    B -->|失败| D[addWaiter]
    D --> E[acquireSharedQueued]

2.2.2 关键方法

  • tryAcquireShared:尝试获取共享资源(返回剩余许可数)
  • doReleaseShared:释放时传播唤醒后续线程

三、关键实现原理

3.1 状态管理

  • compareAndSetState:原子更新state值
    protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }
    
  • 状态传播:共享模式下通过CAS实现状态扩散

3.2 队列操作

  • 入队:通过CAS将节点添加到队尾
    private Node enq(final 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;
                }
            }
        }
    }
    
  • 出队:头节点线程唤醒后尝试获取锁

3.3 线程阻塞与唤醒

  • LockSupport.park():挂起当前线程
  • LockSupport.unpark():唤醒指定线程
  • 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);
    }
    

四、模板方法模式

4.1 方法调用流程

graph TB
    subgraph 获取锁
    A[acquire] --> B{tryAcquire}
    B -->|成功| C[设置独占线程]
    B -->|失败| D[addWaiter]
    D --> E[acquireQueued]
    end
    
    subgraph 释放锁
    F[release] --> G{tryRelease}
    G -->|成功| H[unparkSuccessor]
    end

4.2 需重写方法

方法作用调用时机
tryAcquire尝试获取独占锁acquire()时
tryRelease尝试释放独占锁release()时
tryAcquireShared尝试获取共享锁acquireShared()时
tryReleaseShared尝试释放共享锁releaseShared()时
isHeldExclusively判断是否独占锁条件队列相关操作

五、经典实现案例

5.1 ReentrantLock

// 非公平锁实现
static final class NonfairSync extends Sync {
    final boolean nonfairTryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {
            if (compareAndSetState(0, acquires)) {
                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;
    }
}

5.2 Semaphore

protected int tryAcquireShared(int acquires) {
    for (;;) {
        int available = getState();
        int remaining = available - acquires;
        if (remaining < 0 || compareAndSetState(available, remaining))
            return remaining;
    }
}

六、性能优化策略

6.1 自旋等待

  • 初始自旋次数:JDK1.8动态调整(根据历史成功率)
  • 自适应自旋:减少线程阻塞开销

6.2 锁消除

通过逃逸分析消除无竞争锁:

// 局部变量锁会被消除
public void method() {
    Object lock = new Object();
    synchronized(lock) { // 编译后无同步代码
        // 仅本线程访问
    }
}

6.3 锁粗化

合并相邻同步块:

// 优化前
for(int i=0; i<100; i++) {
    synchronized(lock) { doA(); }
}

// 优化后
synchronized(lock) {
    for(int i=0; i<100; i++) doA();
}

七、设计精髓

  1. 模板方法模式:分离通用逻辑(队列管理)与定制逻辑(状态操作)
  2. 无锁化设计:通过CAS和自旋减少内核态切换
  3. 可扩展性:仅需实现1-4个抽象方法即可创建新同步器
  4. 高并发优化:非公平锁默认策略提升吞吐量