CountDownLatch简单分析
也是利用AQS实现的一个变种,用来预先设置一个阈值(任务数)后主线程调用await()持续阻塞,然后由其他线程执行任务,执行完后调用countDown()将阈值减1,当所有任务执行完毕,阈值减为0,主线程await()被唤醒跳出阻塞,继续执行。
使用例子
public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(2); // 两个任务线程 Worker worker1 = new Worker("A", latch); Worker worker2 = new Worker("B", latch); worker1.start();// worker2.start();// latch.await(); // 阻塞等待所有Worker线程结束 System.out.println("all work done"); } static class Worker extends Thread { private CountDownLatch latch; public Worker(String workerName, CountDownLatch latch){ this.latch = latch; } public void run(){ try{ doWork(); } // 必须放在finally中保证能够释放(不然出异常主线程无法恢复) finally{ latch.countDown(); //线程执行结束, 计数器减1 } } } } |
源码分析
针对AQS的分析见:可重入锁、ReentrantLock、AQS、Condition 和 ReentrantReadWriteLock简单分析。
CountDownLatch的内置Sync类相当简单
- 构造函数,初始化count值,写入AQS的state(相当于已经有count的对象持有锁)
- 主线程调用await()方法,就是执行AQS.acquireSharedInterruptibly,而Sync.tryAcquireShared,只有当state == 0才能够acquire成功(即只有当count减为0,await才会跳出阻塞)
- 其他线程调用countDown()方法,就是执行AQS.releaseShared(1),而Sync.tryReleaseShared,最简单的无限循环阻塞保证release成功
- 多于count数量的执行countDown()方法,不会再更新state值,state减为0就不变了
- 多次await也没有意义,在state==0后,await操作就是共享加锁,都可以瞬间成功
评论 (0)
留下评论