AbstractQueuedSynchronizer简称AQS,ReentrantLock,ReentrantReadWriteLock,CountDownLatch,Semaphore等等这些锁都是基于AQS实现的。AQS核心主要实现了锁的状态的同步,队列排队、唤醒管理,锁的释放等底层功能。主要基于state属性来控制锁的可用状态,通过维护一个CLH双向链表队列来管理并发获取锁的线程进行排队。

主要属性

/**
 * 队列头节点,延迟初始化,除了初始化时仅能通过setHead方法修改
 */
private transient volatile Node head;

/**
 * 队列尾节点,延迟初始化,仅通过enq方法修改添加等待节点
 */
private transient volatile Node tail;

/**
 * 同步器状态
 */
private volatile int state;

CLH队列节点属性

static final class Node {
    /** 共享锁标记 */
    static final Node SHARED = new Node();
    /** 独占锁标记 */
    static final Node EXCLUSIVE = null;

    /** 节点取消排队,可能由于超时或者中断 */
    static final int CANCELLED =  1;
    /** 当前节点的下个节点是阻塞或即将阻塞,当节点释放锁或取消时应该唤醒unpark下个节点 */
    static final int SIGNAL    = -1;
    /** 条件队列节点 */
    static final int CONDITION = -2;
    /**
     * 标识下个节点无条件传播(适用与共享锁)
     */
    static final int PROPAGATE = -3;

    //节点等待状态,0,CANCELLED,SIGNAL,CONDITION,PROPAGATE
    volatile int waitStatus;

    //上个节点
    volatile Node prev;

    //下个节点
    volatile Node next;

    //节点线程
    volatile Thread thread;

    /**
     * 共享锁时值为 SHARED
     * 条件队列时指向条件队列下个节点
     */
    Node nextWaiter;

加锁流程

image.png

核心方法

//判断当前请求是否需要排队
public final boolean hasQueuedPredecessors() {
    Node t = tail;//尾节点
    Node h = head;//头节点
    Node s;
    return h != t &&//h==t时代表没有线程排队,见:java.util.concurrent.locks.AbstractQueuedSynchronizer#enq()
        ((s = h.next) == null || s.thread != Thread.currentThread());
        //
        //s.thread != Thread.currentThread() 判断第一个排队线程是否是当前线程
}

lane
1 声望1 粉丝