1. 程式人生 > >CountDownLatch 原始碼分析

CountDownLatch 原始碼分析

CountDownLatch

(鎖存器/閉鎖)是基於同步器實現的同步輔助類,在完成一組正在其他執行緒中執行的操作之前,它允許一個或多個執行緒一直等待。
用計數值 N 初始化的 CountDownLatch 可以使一個或多個執行緒在其他 N 個執行緒完成某項操作之前一直等待,或者使其在某項操作完成 N 次之前一直等待。

建立例項

    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;

        Sync(int count) {
            // 寫入狀態值
            setState(count);
        }

        int getCount() {
            return getState();
        }

        /**
         *  只有當同步狀態為 0 時才能獲取成功,否則進入阻塞
         * created by ZXD at 15 Dec 2018 T 12:05:56
         * @param acquires
         * @return
         */
        @Override
        protected int tryAcquireShared(int acquires) {
            return getState() == 0 ? 1 : -1;
        }

        /**
         *  嘗試將狀態值遞減 1,如果遞減到 0,則釋放在閉鎖上阻塞等待的所有執行緒
         */
        @Override
        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                final int c = getState();
                if (c == 0) {
                    return false;
                }
                // 狀態值遞減 1
                final int nextc = c - 1;
                if (compareAndSetState(c, nextc)) {
                    // 已經遞減到 0,則返回 true
                    return nextc == 0;
                }
            }
        }
    }

    private final Sync sync;

    /**
     *  建立計數值為 count 的閉鎖
     */
    public CountDownLatch(int count) {
        if (count < 0) {
            throw new IllegalArgumentException("count < 0");
        }
        sync = new Sync(count);
    }

同步阻塞

    /**
     *  阻塞等待閉鎖的狀態值遞減到 0、或執行緒被中斷為止
     */
    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    /**
     *  在指定的超時時間內阻塞等待閉鎖的狀態值遞減到 0、或執行緒被中斷為止
     */
    public boolean await(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

遞減閉鎖狀態值,如果遞減到 0,則釋放所有在閉鎖上阻塞等待的執行緒

    /**
     *  遞減閉鎖狀態值,如果遞減到 0,則釋放所有在閉鎖上阻塞等待的執行緒
     */
    public void countDown() {
        sync.releaseShared(1);
    }