Java并发编程之AQS源码阅读

1. 父类AbstractOwnableSynchronizer

该类有两个重要的方法,设置独占线程与获取独占线程。

public abstract class AbstractOwnableSynchronizer
    implements java.io.Serializable {

    /** Use serial ID even though all fields transient. */
    private static final long serialVersionUID = 3737899427754241961L;

    /**
     * 空构造方法
     */
    protected AbstractOwnableSynchronizer() { }

    /**
     * 同步器独占模式当前线程
     */
    private transient Thread exclusiveOwnerThread;

    /**
     * 设置当前独占线程
     */
    protected final void setExclusiveOwnerThread(Thread thread) {
        exclusiveOwnerThread = thread;
    }

    /**
     * 获取当前独占线程
     */
    protected final Thread getExclusiveOwnerThread() {
        return exclusiveOwnerThread;
    }
}

2. Node节点

用Node作为同步队列和条件队列的节点。

    static final class Node {
        /** 共享模式中的节点 */
        static final Node SHARED = new Node();
        /** 独占模式中的节点 */
        static final Node EXCLUSIVE = null;

        /** 当线程等待超时或者被中断,则取消等待,设等待状态为-1,进入取消状态则不再变化 */
        static final int CANCELLED =  1;
        /** 后继节点处于等待状态,当前节点(为-1)被取消或者中断时会通知后继节点,使后继节点的线程得以运行 */
        static final int SIGNAL    = -1;
        /** 当前节点处于等待队列,节点线程等待在Condition上,当其他线程对condition执行signall方法时,等待队列转移到同步队列,加入到对同步状态的获取 */
        static final int CONDITION = -2;
        /**
         * 值为-3,与共享模式相关,在共享模式中,该状态标识结点的线程处于可运行状态
         */
        static final int PROPAGATE = -3;

        /**
         * 等待状态
         */
        volatile int waitStatus;

        /**
         * 指向前节点
         */
        volatile Node prev;

        /**
         * 指向后节点
         */
        volatile Node next;

        /**
         * 进入该节点的线程
         */
        volatile Thread thread;

        /**
         * 指向条件队列中的下一个节点
         */
        Node nextWaiter;

        /**
         * 当节点在共享模式中等待时返回true
         */
        final boolean isShared() {
            return nextWaiter == SHARED;
        }

        /**
         * 返回前一节点
         */
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }

        Node() {    // Used to establish initial head or SHARED marker
        }

        Node(Thread thread, Node mode) {     // 被addWaiter方法调用
            this.nextWaiter = mode;
            this.thread = thread;
        }

        Node(Thread thread, int waitStatus) { // 被条件队列使用
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }

3. 成员变量

包含三个成员变量,head、tail以及state

    /**
     * 等待队列的头结点,如果头结点存在的话,它的waitStatus不能是CANCELLED
     */
    private transient volatile Node head;

    /**
     * 等待队列的尾节点
     */
    private transient volatile Node tail;

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

4. 主要方法

4.1 同步器状态相关

    /**
     * 获取当前同步器状态
     */
    protected final int getState() {
        return state;
    }

    /**
     * 设置当前同步器状态
     */
    protected final void setState(int newState) {
        state = newState;
    }

    /**
     * 调用魔法类的CAS方法,设置同步器状态
     */
    protected final boolean compareAndSetState(int expect, int update) {
        // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

4.2 acquire(int arg)方法

先尝试获取同步状态,如果获取成功(同步状态为0,表示可以获取),直接返回;否则该线程加到等待队列中进行排队。

    /**
     * 以独占模式获取,忽略中断。 通过调用至少一次tryAcquire(int)实现,成功返回。
     * 否则线程排队,可能会重复阻塞和解除阻塞,直到成功才调用tryAcquire(int) 。 该方法可用于实现方法Lock.lock() 。
     */
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

4.3 tryAcquire(int arg)方法

交给子类实现

4.4 addWaiter(Node mode)方法

将新节点加到尾部

    /**
     * 在尾部添加节点
     */
    private Node addWaiter(Node mode) {
        // 构建一个新node,nextWaiter是当前node
        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;
    }

4.5 enq(final Node node)方法

将当前节点入队。

    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;
                }
            }
        }
    }

4.6 acquireQueued(final Node node, int arg)方法

不断自旋尝试获取同步状态(锁),获取不成功,则阻塞节点中的线程。

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; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())    // 休眠线程并返回中断状态
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

4.7 release(int arg)方法

在独占模式中释放节点。当返回true的时候,unblocking一个或多个线程。

    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

4.8 tryRelease(int arg)方法

尝试释放同步状态,留给子类实现

    protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
    }

4.9 unparkSuccessor(Node node)方法

唤醒线程

private void unparkSuccessor(Node node) {
        // 获取wait状态
        int ws = node.waitStatus;
        if (ws < 0)
            compareAndSetWaitStatus(node, ws, 0);

        /**
         * 若后继结点为空,或状态为CANCEL(已失效),则从后尾部往前遍历找到最前的一个处于正常阻塞状态的结点
         * 进行唤醒
         */
        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.10 acquireShared(int arg)方法

在共享模式中获得锁。

    public final void acquireShared(int arg) {
        if (tryAcquireShared(arg) < 0)
            doAcquireShared(arg);
    }

4.11 tryAcquireShared(int arg)

尝试获取锁,当返回值大于等于0时,表示能够获取到同步状态,空方法留给子类实现。

4.12 doAcquireShared(int arg)方法

如果当前节点的前驱为头节点时,尝试获取同步状态

private void doAcquireShared(int arg) {
        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
                        if (interrupted)
                            selfInterrupt();
                        failed = false;
                        return;
                    }
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

4.13 releaseShared(int arg)方法

该方法在释放同步状态之后,将会唤醒后续处于等待状态的节点。对于能够支持多个线 程同时访问的并发组件(比如Semaphore),它和独占式主要区别在于tryReleaseShared(int arg) 方法必须确保同步状态(或者资源数)线程安全释放,一般是通过循环和CAS来保证的,因为 释放同步状态的操作会同时来自多个线程。

    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }

你可能感兴趣的:(Java并发编程之AQS源码阅读)