【java并发】CountDownLatch源码解析

本文深入解析了CountDownLatch的原理与应用,介绍了其通过AQS实现的内部机制,包括构造函数、await()、await(long timeout, TimeUnit unit)和countDown()方法,并提供了实际使用案例。

一、概述

CountDownLatch是限制某个线程等待其他线程全部执行后再执行;
相当于有一个计数器,每执行一个线程计数器-1,知道计数器为0;在等待的线程便可以继续执行。
一般用于主线程需要使用多线程计算的结果

二、源码解析

CountDownLatch同步器通过AQS实现,使用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) {
            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;
            }
        }
    }
  1. 初始化给定state初始值
  2. 获取共享锁必须在state等于0才能获取成功
  3. 释放锁就是给计数器state减一
1、构造函数

CountDownLatch只提供了一个构造函数,必须指定大于0的计数器初始值

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

await其实就是获取锁,成功则继续执行,失败则加入AQS队列自旋、休眠等待唤醒,直至成功获取锁

    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
    // Sync中实现
	protected int tryAcquireShared(int acquires) {
         return (getState() == 0) ? 1 : -1;
     }

只有当state=0时才能获取锁成功

3、await(long timeout, TimeUnit unit)

有超时时间的等待,如果在超时时间内没有获取锁,则立即返回false,线程继续

    public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }
4、countDown()

countDown其实就是释放共享锁

	public void countDown() {
        sync.releaseShared(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;
            }
        }

如果state计数器没有归零,则不断自旋,直至成功释放,或者计数器归零

三、使用实例

private static AtomicInteger atomicInteger = new AtomicInteger();

    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(100);
        for (int i = 0; i < 100; i++) {
            new Thread(new TestThread(countDownLatch)).start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("result:" + atomicInteger.get());
    }

    private static class TestThread implements Runnable {

        private CountDownLatch countDownLatch;

        TestThread(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            try {
                System.out.println(atomicInteger.incrementAndGet());
            } finally {
                countDownLatch.countDown();
            }
        }
    }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值