AbstractQueuedSynchronizer

109 阅读5分钟

多线程并发目的是控制哪个线程独占资源运行或者多个线程共享资源在运行, 其他线程入队阻塞, 当资源被释放时唤醒队列中一个或者多个线程运行.

  * <pre>
     *      +------+  prev +-----+       +-----+
     * head |      | <---- |     | <---- |     |  tail
     *      +------+       +-----+       +-----+
     * </pre>
  *
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;
        /**指示节点线程在等待condition. */
        static final int CONDITION = -2;
        /**
         *指示下一个acquireShared应该无条件传播
         */
        static final int PROPAGATE = -3;

        /**
         * Status field, taking on only the values:
         *   SIGNAL:     该节点线程后继节点线程是阻塞态, 因此当前节点线程释放或者取消需要取消阻塞后继节点线程.为了避免争用,acquire方法必须首先指示它们需要一个信号,然后重试原子获取,然后在失败时阻塞。
         *   CANCELLED:  由于超时或中断,此节点被取消。节点永远不会离开此状态。特别地,具有取消节点的线程不再阻塞。
         *   CONDITION:  此节点当前位于条件队列中。它不会用作同步队列节点.直到转移,此时的状态将设置为0。
         *   PROPAGATE:  传播
         */
        volatile int waitStatus;

        /**
     		前驱节点, 找到一个非取消的,它将一直存在作为head
         */
        volatile Node prev;

        /**
         后继节点
         */
        volatile Node next;

        /**
         * 节点线程
         */
        volatile Thread thread;

        /*
         */
        Node nextWaiter;

        /**
         * Returns true if node is waiting in shared mode.
         */
        final boolean isShared() {
            return nextWaiter == SHARED;
        }

        /** 前驱节点获取,不允许null
         */
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }

        /** Establishes initial head or SHARED marker. */
        Node() {}

        /** Constructor used by addWaiter. */
        Node(Node nextWaiter) {
            this.nextWaiter = nextWaiter;
            U.putObject(this, THREAD, Thread.currentThread());
        }

        /** Constructor used by addConditionWaiter. */
        Node(int waitStatus) {
            U.putInt(this, WAITSTATUS, waitStatus);
            U.putObject(this, THREAD, Thread.currentThread());
        }

        /** CASes waitStatus field. 
        expect 期待值
        update 更新值(在waitStatus是期待值情况下才允许更新waitStatus为update值)
        */
        final boolean compareAndSetWaitStatus(int expect, int update) {
            return U.compareAndSwapInt(this, WAITSTATUS, expect, update);
        }

        /** CASes next field. */
        final boolean compareAndSetNext(Node expect, Node update) {
            return U.compareAndSwapObject(this, NEXT, expect, update);
        }

        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
        private static final long NEXT;
        static final long PREV;
        private static final long THREAD;
        private static final long WAITSTATUS;
        static {
            try {
            	// CAS对象前驱指针、后继指针、节点线程、waitStatus
                NEXT = U.objectFieldOffset
                    (Node.class.getDeclaredField("next"));
                PREV = U.objectFieldOffset
                    (Node.class.getDeclaredField("prev"));
                THREAD = U.objectFieldOffset
                    (Node.class.getDeclaredField("thread"));
                WAITSTATUS = U.objectFieldOffset
                    (Node.class.getDeclaredField("waitStatus"));
            } catch (ReflectiveOperationException e) {
                throw new Error(e);
            }
        }
    }
 /**
     * 队列头节点, 懒初始化.除了初始化, 只能通过setHead方法设置,head节点应该保证不为CANCELLED状态
     */
    private transient volatile Node head;

    /**
     * 队列尾节点,懒初始化.只能通过入队修改Tail尾节点
     */
    private transient volatile Node tail;

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

	// 此操作具有{@code volatile}读取的内存语义。
	protected final int getState() {
        return state;
    }

    /**
     * 此操作具有{@code volatile}写的内存语义。
     * @param newState the new state value
     */
    protected final void setState(int newState) {
        state = newState;
    }

    /**
     * 以原子方式将同步状态设置为给定的更新值,如果当前状态值等于预期值。
     * 此操作具有{@code volatile}读和写的内存语义。
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that the actual
     *         value was not equal to the expected value.
     */
    protected final boolean compareAndSetState(int expect, int update) {
        return U.compareAndSwapInt(this, STATE, expect, update);
    }
// 节点入队尾,新节点前驱prev指向当前尾节点tail, 当前尾节点tail后继next指向该节点,更新尾节点tail指向该新节点
// 无限cas直到成功
// 头节点指向一个没实体的节点(前驱null、thread null), 尾节点指向的最后插入队列的节点
private Node enq(Node node) {
        for (;;) {
            Node oldTail = tail;
            if (oldTail != null) {
            	// 该新节点前驱prev指向原尾节点oldTail
                U.putObject(node, Node.PREV, oldTail);
                // cas尾节点tail指向该新节点 (tail = node)
                if (compareAndSetTail(oldTail, node)) {
                	// 原尾节点next指向该新节点
                    oldTail.next = node;
                    // 返回原来尾节点
                    return oldTail;
                }
            } else {
            	// 尾节点空, 队列空, 需要初始化队列
                // 新建一个节点, head 、tail都指向该节点
                initializeSyncQueue();
            }
        }
    }

	/**
     * 初始化头节点和尾节点
     */
    private final void initializeSyncQueue() {
        Node h;
        // HEAD指示的是头节点, 如果头节点当前值为null, 则new一个节点h, 将头节点head指向该节点, 成功之后将尾节点tail指向该节点
        if (U.compareAndSwapObject(this, HEAD, null, (h = new Node())))
            tail = h;
    }

    /**
     * cas尾节点tail
     * expect期望值
     * update更新值
     */
    private final boolean compareAndSetTail(Node expect, Node update) {
        return U.compareAndSwapObject(this, TAIL, expect, update);
    }
	// acquire才允许调用, head指向该节点, 该节点前驱prev置null, thread置null
    // 头节点指向一个没实体的节点(前驱null、thread null), 尾节点指向的最后插入队列的节点, 尾节点是有实体线程的
	private void setHead(Node node) {
        head = node;
        node.thread = null;
        node.prev = null;
    }

// 唤醒节点的后继节点
private void unparkSuccessor(Node node) {
        /*
         * If status is negative (i.e., possibly needing signal) try
         * to clear in anticipation of signalling.  It is OK if this
         * fails or if status is changed by waiting thread.
         */
        int ws = node.waitStatus;
        if (ws < 0)
            node.compareAndSetWaitStatus(ws, 0);

        /*
         * 后继节点取消阻塞, 当后继节点为null或者是cancel状态
         * 从尾节点往前找一个最靠近node但是非该node非null满足非cancel的节点
         * 为什么从后面往前查找?而不是从前往后查找?
         * enq插入队尾, cas修改tail尾节点之后, 需要将原tail节点next指向新尾节点 oldTail.next=node , 若该方法调用发生在这之前可能遍历不到所有节点 ?
         */
        Node s = node.next;
        if (s == null || s.waitStatus > 0) {
            s = null;
            for (Node p = tail; p != node && p != null; p = p.prev)
                if (p.waitStatus <= 0)
                    s = p;
        }
        if (s != null)
            LockSupport.unpark(s.thread);
    }
// 获取失败之后是否应该阻塞
// 在前驱节点signal状态之后才允许阻塞
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
		
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL)
            /*
           	 * 前驱节点signal状态,允许阻塞, 因为前驱节点会通知
             */
            return true;
        if (ws > 0) {
            /*
             * 前驱节点cancel状态, 往前找到非cancel状态的节点作为新前驱节点
             */
            do {
            	// pred = pred.prev
                // node.prev = pred
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            /*
        	 * 如果前面其他节点也都不满足非cancel,将pred节点 cas 为signal
             * 调用此方法的但是不能在阻塞之前获取
             */
            pred.compareAndSetWaitStatus(ws, Node.SIGNAL);
        }
        return false;
    }
	private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);
        return Thread.interrupted();
    }
	final boolean acquireQueued(final Node node, int arg) {
        try {
            boolean interrupted = false;
            // 自旋重试
            for (;;) {
            	// 获取该节点的前驱节点
                final Node p = node.predecessor();
                // 如果前驱节点是头节点, 允许尝试获取
                if (p == head && tryAcquire(arg)) {
                	// 获取成功
                    // head节点指向该节点node
                    setHead(node);
                    // 回收原head节点
                    p.next = null; // help GC
                    return interrupted;
                }
                // 前驱节点非头节点, 阻塞当前节点线程, 
                // 当获得锁线程释放之后, 会unpark后继节点, 
                // 后继节点从阻塞中出来再自旋重试获取资源
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } catch (Throwable t) {
            cancelAcquire(node);
            throw t;
        }
    }
	private void doAcquireInterruptibly(int arg)
        throws InterruptedException {
        final Node node = addWaiter(Node.EXCLUSIVE);
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    return;
                }
                // 不断自旋直至将前驱结点状态设置为SIGNAL,然后阻塞当前线程
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    // 抛出中断异常退出自旋
                    throw new InterruptedException();
            }
        } catch (Throwable t) {
            cancelAcquire(node);
            throw t;
        }
    }
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

   public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
            	// 头节点不为cancel态,取消后继节点阻塞
                unparkSuccessor(h);
            return true;
        }
        return false;
    }