CountDownLatch的基础和原理

2 阅读1分钟

什么是CountDownLatch?

CountDownLatchjuc包下的一个同步辅助类。它允许一个或多个线程等待其他一组线程完成操作,再继续执行。

用法:

  • 构造时​ 设定一个初始计数值(比如 N)。

  • 等待线程​ 调用 await()方法,会被阻塞,直到计数器减到 0。

  • 工作线程​ 在完成某项任务后,调用 countDown()方法,将计数器减 1。

CountDownLatch原理

构造器原理

    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

这个构造器本质是为Sync构造,赋值state

countDown原理

    public void countDown() {
        sync.releaseShared(1);
    }
    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            signalNext(head);
            return true;
        }
        return false;
    }

countDown的本质是释放一个资源。

        protected boolean tryReleaseShared(int releases) {
            // 自旋CAS,通过state==0来判断释放要唤醒线程
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c - 1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }

非常普通的一个自旋CAS

await原理

    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
    public final void acquireSharedInterruptibly(int arg)
        throws InterruptedException {
        if (Thread.interrupted() ||
            (tryAcquireShared(arg) < 0 &&
             acquire(null, arg, true, true, false, 0L) < 0))
            throw new InterruptedException();
    }

await的本质是获取共享锁

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

重写后的tryAcquireShared粗俗易懂,当state==0就可以获得锁,不等于零直接阻塞。