美文网首页
AQS源码浅析(9)——CountDownLatch

AQS源码浅析(9)——CountDownLatch

作者: 墨_0b54 | 来源:发表于2022-04-27 19:57 被阅读0次

    CountDownLatch是共享锁的一种实现, 它默认构造 AQS 的 state 值为 count,允许n(int最大值)个线程阻塞在一个地方,直至所有线程的任务都执行完毕。

    • 当调用 await方法的时候,如果 state 不为 0,那就证明任务还没有执行完毕,await() 方法就会一直阻塞。
    • 当线程使用 countDown方法时,其实使用了tryReleaseShared方法来减少 state直到为 0 ,就会释放所有等待的线程。
    • CountDownLatch是一次性的,看看源码实现,state不能被恢复
    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) { //state不为0时阻塞
            return (getState() == 0) ? 1 : -1;
        }
        protected boolean tryReleaseShared(int releases) {//state不为0时减1
            // 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;
            }
        }
    }
    

    CountDownLatch 的两种典型用法

    1、某一线程在开始运行前等待 n 个线程执行完毕。

    将 CountDownLatch 的计数器初始化为 n (new CountDownLatch(n)),每当一个任务线程执行完毕,就将计数器减 1 (countdownlatch.countDown()),当计数器的值变为 0 时,在 CountDownLatch 上 await() 的线程就会被唤醒。一个典型应用场景就是启动一个服务时,主线程需要等待多个组件加载完毕,之后再继续执行。

    2、实现多个线程开始执行任务的最大并行性。

    注意是并行性,不是并发,强调的是多个线程在某一时刻同时开始执行。类似于赛跑,将多个线程放到起点,等待发令枪响,然后同时开跑。做法是初始化一个共享的 CountDownLatch 对象,将其计数器初始化为 1 (new CountDownLatch(1)),多个线程在开始执行任务前首先 coundownlatch.await(),当主线程调用 countDown() 时,计数器变为 0,多个线程同时被唤醒。

    相关文章

      网友评论

          本文标题:AQS源码浅析(9)——CountDownLatch

          本文链接:https://www.haomeiwen.com/subject/spqssrtx.html