Java - CountDownLatch 源码阅读笔记

in TCEH Java

简介

   CountDownLatch是同步辅助工具类。实现指定计数减小为0时,一个或多个被阻塞的线程才会继续往下执行。与CyclicBarrier正好相反,只能一次性使用,不支持循环使用。

示例

@Log4j2
public class CountDownLatchTest {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(2);
        new Thread(() -> {
            try {
                log.info("子线程等待!");
                latch.await();
                log.info("子线程执行完毕!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> latch.countDown()).start();
        // new Thread(() -> latch.countDown()).start();
        log.info("主线程等待!");
        latch.await();
        log.info("主线程执行完毕!");
    }
}

构造方法

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

Sync 类

与CyclicBarrier使用可重入锁实现线程阻塞不一样,这里使用抽象队列同步器

    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) {
            // CAS自旋修改count减1
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
    }

await() 方法

直接依赖AbstractQueuedSynchronizer来实现

    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

countDown() 方法

直接依赖AbstractQueuedSynchronizer来实现

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