JUC下工具類CountDownLatch用法以及源碼理解

CountDownLoatch是JUC下一個用於控制計數的計數器,好比我須要從6開始計數,每一個線成運行完以後計數減一,等計數器到0時候開始執行其餘任務。java

public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 0; i < 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t結束");
                countDownLatch.countDown();
            }, String.valueOf(i)).start();
        }
        countDownLatch.await();
        System.out.println("開始執行新任務");
    }

如今讓咱們來看下CountDownLoach的底層源碼函數

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

        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }

        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
    }

    private final Sync sync;

這裏最重要的是這個tyrReleaseShared方法,CountDownLatch也是實現了AQS機制,經過state去判斷資源知否被佔用。當咱們使用countDow函數去減1時,會觸發releaseShared方法,這個方法的參數時每次減的次數,默認是1oop

public void countDown() {
        sync.releaseShared(1);
}

咱們點進去看看這個方法是如何實現的ui

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

這個方法調用了AQS的releaseShared,他會先去嘗試減一,判斷是否減一成功spa

protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }

這裏使用了CAS自旋機制對state(咱們這裏是6)進行減1,若是自旋成功就會返回true即6一個一個減最後變成0,就會執行下面的doReleaseShared方法code

private void doReleaseShared() {
        for (;;) {
            Node h = head;
            if (h != null && h != tail) {
                int ws = h.waitStatus;
                if (ws == Node.SIGNAL) {
                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                        continue;            // loop to recheck cases
                    unparkSuccessor(h);
                }
                else if (ws == 0 &&
                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                    continue;                // loop on failed CAS
            }
            if (h == head)                   // loop if head changed
                break;
        }
    }

這裏使用了LockSupport相關的加鎖解鎖,unpark有關這個我會在以後有空的時候進行解析,經過對AQS任務隊列進行判斷,是否只有頭節點和尾節點,這個任務隊列裏面頭節點並非真正的任務,而是爲了初始化方便操做的哨兵節點,而後對第一個任務節點進行操做,就是咱們這6步操做,每次減一做爲一個任務進行釋放(我本身認爲的)。blog

 

這是我第一次發帖子但願你們多多支持,準備秋招了,爭取大廠上岸,若是帖子裏有錯誤但願你們積極提出來隊列

相關文章
相關標籤/搜索