AbstractQueuedSynchronizer(aqs) 源码解析 --- 独享锁模式

198 阅读6分钟

aqs独享锁模式源码

package java.util.concurrent.locks;

public abstract class AbstractQueuedSynchronizer
    // AbstractOwnableSynchronizer 独享锁专用, 维护当前持锁线程, 兼容可重入锁
    extends AbstractOwnableSynchronizer
    implements java.io.Serializable {

    // aqs继承序列化类有什么用?  带锁网络传输
    private static final long serialVersionUID = 7373984972572414691L;

    // 抽象队列同步器  (自旋+阻塞  CLH自选锁变体 隐式链表队列锁)
    protected AbstractQueuedSynchronizer() { }
    
    /*
     *      +------+  prev +-----+       +-----+
     * head |      | <---- |     | <---- |     |  tail
     *      +------+       +-----+       +-----+
     */
    static final class Node {
        /** 独享模式 */
        static final Node EXCLUSIVE = null;

        /** 取消 */
        static final int CANCELLED =  1;
        /** 当前节点为SIGNAL, 释放锁时会unpark 后续节点.*/
        static final int SIGNAL    = -1;
        // 独占锁, 只用到以上两种状态

        /**
         * 普通同步节点 初始化为0
         * 使用CAS修改状态 或者  volatile set(尽量使用无条件volatile写入 性能会好一些).
         */
        volatile int waitStatus;
        
        volatile Node prev;
        
        volatile Node next;

        // 节点线程.  构造时初始化 使用后置null.
        volatile Thread thread;

        /**
         * 返回前驱节点.  
         * 可以忽略null, NullPointerException help VM.
         */
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }

        Node() {    // 用于创建head
        }
        
        Node(Thread thread, Node mode) {     // 创建独享锁节点
            this.nextWaiter = mode;
            this.thread = thread;
        }
        
    }

    /**
     * 等待队列头 懒加载.  除了初始化之外,它只通过setHead方法进行修改。  
     * Note: 如果head存在, 它的等待状态 != CANCEL
     */
    private transient volatile Node head;

    // 等待队列尾 懒加载.  通过方法enq, 添加新的等待节点.
    private transient volatile Node tail;
    
    /** 
     * 独享模式下保证线程互斥, 只有一个线程进入临界区, 其他等待。
     * 同步状态 不同数值代表:获得锁,释放锁
     * 数值可以自定义  比如1: 获得锁   0:释放锁
     * 在tryAcquire tryRelease 中使用
     * tryAcquire tryRelease 需要用户实现且互斥
     * 虽然 JSR-166 对64-bit long支持原子性操作,  需要不同平台的内部锁的支持,造成同步器性能不行.
     */
    private volatile int state;

    // memory semantics 读内存语义
    protected final int getState() {
        return state;
    }

    // memory semantics 写内存语义
    protected final void setState(int newState) {
        state = newState;
    }

    // 具有读写的内存语义
    protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }
    // Main exported methods   主要对外开放接口

    /**
     * 尝试获取独享锁. 这个方法查询对象是否允许以独占模式获得它.
     *
     * 线程执行此方法尝试获取锁,获取失败如果未排队,acquire method会调用入队方法
     */
    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * 尝试set state(int类型 不同数值代表 获得锁 释放锁)
     * <p>总是在 thread 执行 release 时被调用.
     *
     * @param arg the release argument. 这个值会经过release传进来,
     * @throws IllegalMonitorStateException 如果释放使同步器处于非法状态
     * @throws UnsupportedOperationException 如果不支持独享模式
     */
    protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * 独占锁模式获取, ignoring interrupts. 
     * 如果{@link #tryAcquire}返回获得锁失败, thread将阻塞并排队, 
     * 线程可能反复的阻塞唤醒, 知道 {@link #tryAcquire} 成功. 
     */
    public final void acquire(int arg) {
        // 如果tryAcquire成功, 不加入等待队列, 提高效率.
        if (!tryAcquire(arg) &&
            // addWaiter: 创建节点加入等待队列
            // acquireQueued 将队列的前一个节点状态设置为signal
            // signal状态的节点释放锁时能唤醒下一个节点
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

    // 释放独享锁. 唤醒队列中的下一个节点去争抢锁
    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            // --------------- tryRelease ---------------
            // 当tryRelease return true 才能进入下面的方法, 安全区
            Node h = head;
            // h.waitStatus 不能为cancel 不能为0 只剩下signal
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
            // --------------- tryRelease ---------------
        }
        return false;
    }
    /*----------------- 队列方法 -----------------*/

    // 插入队尾, 必要时初始化
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { // 懒加载
                // 此处和 setHead 有访问冲突, 使用cas防止数据争用
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
                node.prev = t;
                // cas 可分解为读写两步 性能消耗也相当于volatile 读写:
                // 1. 比较 pred 和 当前的 tail
                // 2. 如果 pred == tail 将 tail 替换成 node
                // 3. 如果 pred != tail 调用 enq(node)
                // cas是原子性操作, 确保 (pred)oldTail 和 node(new tail) 的前后关系
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }

    /**
     * 节点的 创建/插入队尾
     * @param mode Node.EXCLUSIVE 独享锁, Node.SHARED 共享锁
     */
    private Node addWaiter(Node mode) {
        // new Node() 无需考虑ABA问题
        Node node = new Node(Thread.currentThread(), mode);
        // 尝试最短路径入队; 失败使用 完整的 enq;
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }

    /**
     * 插入表头, 退出等待队列. 仅仅通过acquire调用.
     * 防止不必要的 唤醒信号和遍历
     */
    private void setHead(Node node) {
        head = node;
        // 置空, 为了方便GC, 防止不必要的 唤醒信号和遍历
        node.thread = null;
        node.prev = null;
    }

    // 唤醒后继结点
    private void unparkSuccessor(Node node) {
        int ws = node.waitStatus;
        if (ws < 0) 
            // 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);
    }

    // acquire 工具类
    // 修改pred节点状态为Signal
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        // 前一个Node状态为SIGNAL, 当前节点可以被唤醒, 可以安全的park当前节点
        if (ws == Node.SIGNAL)  
            return true;
        // 其他情况 返回false 
        if (ws > 0) { //取消状态
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            // waitStatus must be 0(独享锁模式) or PROPAGATE(共享锁模式). 修改为 SIGNAL
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }

    static void selfInterrupt() {
        // 中断当前线程
        Thread.currentThread().interrupt();
    }

    private final boolean parkAndCheckInterrupt() {
        // 挂起线程
        LockSupport.park(this);
        // 返回中断状态  
        return Thread.interrupted();
    }

    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            // 自选锁
            for (;;) {
                final Node p = node.predecessor();
                // 前节点是head && 尝试获取锁
                if (p == head && tryAcquire(arg)) {
                    // 当前节点设置为头节点
                    // ------------ tryAcquire 安全区 ------------
                    // 只有获得锁的线程能够执行 执行以下代码保证了头节点的同步安全
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                    // ------------ tryAcquire 安全区 ------------
                }
                // shouldParkAfterFailedAcquire 获取锁失败后,设置前一个节点为SINGAL
                if (shouldParkAfterFailedAcquire(p, node) &&
                    // parkAndCheckInterrupt 挂起线程并检查是否中断
                    parkAndCheckInterrupt()){  // 被唤醒后重新走一遍当前流程
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
    
    private void cancelAcquire(Node node) {
        if (node == null)
            return;

        node.thread = null;

        Node pred = node.prev;
        while (pred.waitStatus > 0)
            node.prev = pred = pred.prev;

        Node predNext = pred.next;

        node.waitStatus = Node.CANCELLED;

        if (node == tail && compareAndSetTail(node, pred)) {
            compareAndSetNext(pred, predNext, null);
        } else {
            int ws;
            if (pred != head &&
                ((ws = pred.waitStatus) == Node.SIGNAL ||
                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
                pred.thread != null) {
                Node next = node.next;
                if (next != null && next.waitStatus <= 0)
                    compareAndSetNext(pred, predNext, next);
            } else {
                unparkSuccessor(node);
            }

            node.next = node; // help GC
        }
    }
    // cas 原子性操作 无锁同步
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long stateOffset;
    private static final long headOffset;
    private static final long tailOffset;
    private static final long waitStatusOffset;

    static {
        try {
            // 获取对象属性内存地址
            stateOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
            headOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
            tailOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
            waitStatusOffset = unsafe.objectFieldOffset
                (Node.class.getDeclaredField("waitStatus"));

        } catch (Exception ex) { throw new Error(ex); }
    }

    // CAS head field. Used only by enq.
    private final boolean compareAndSetHead(Node update) {
        return unsafe.compareAndSwapObject(this, headOffset, null, update);
    }

    // CAS tail field. Used only by enq.
    private final boolean compareAndSetTail(Node expect, Node update) {
        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
    }

    // CAS waitStatus field of a node.
    private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) {
        return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update);
    }
}

列举  aqs 独享锁中 中的共享变量
1. volatile int state
2. Node() { 
    volatile int waitStatus
	volatile Node prev;
3. volatile Node head
4. volatile Node tail
列举  aqs 独享锁中 涉及同步动作,同步顺序的代码
protected final int getState() {
    return state;
}

protected final void setState(int newState) {
    state = newState;
}

protected final boolean compareAndSetState(int expect, int update) {
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
    
private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) {
    return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update);
}

private final boolean compareAndSetHead(Node update) {
    return unsafe.compareAndSwapObject(this, headOffset, null, update);
}

private final boolean compareAndSetTail(Node expect, Node update) {
    return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}

// 都是无锁cas的方法 或者 volatile的读/写
// cas保证原子性的同时 性能消耗约等于 volatile 读+写