CountDownLatch和CyclicBarrier区别与原理(图解)

CountDownLatch和CyclicBarrier区别与原理(图解)-mikechen

CyclicBarrierCountDownLatchJava并发工具类,并且平时很多场景都会使用到,本文详解两者的原理和区别@mikechen

CountDownLatch原理

CountDownLatch简介

CountDownLatch就是一个或者一组线程在开始执行操作之前,必须要等到其他线程执行完才可以。

例如:应用程序的主线程,希望在负责启动框架服务的线程,启动所有的框架服务之后,最后再执行。

例如倒数计时器:一种典型的场景就是火箭发射,在火箭发射前,为了保证万无一失,往往还要进行各项设备、仪器的检查。

除了刚提到的技术场景,生活中场景也是非常多的,比如:在考试的时候,老师必须要等到所有人交了试卷才可以走。

以上这些场景,都是非常适合使用CountDownLatch的。

 

CountDownLatch实现原理

CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。

每当一个线程完成了自己的任务后,计数器的值就会减1,当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。

如下图所示:

CountDownLatch和CyclicBarrier区别与原理(图解)-mikechen

整个的实现步骤,大致可以分为如下3步:

第一步:初始计数器

// 等待线程的数量为10
CountDownLatch c = new CountDownLatch(10);

第二步:主线程阻塞

此时,主线程调用CountDownLatch的await()方法,阻塞当前线程(即:主线程在闭锁上等待),直到计数器的值为0。

//主线程在闭锁上等待,直到计数器的值为0
countDownLatch.await()

第三步:计数器减1

主线程闭锁等待后,子线程开始执行任务,每当一个线程完成了自己的任务后,调用CountDownLatch的countDown()方法,计数器的值就会减1,如下所示:

//countDown():计数器减一,表示线程完成任务
CountDownLatch.countDown()

上面的初始线程10陆续减完,当计数器值到达0时,它表示所有的线程已经完成了任务,此时,在闭锁上等待的主线程就可以恢复执行任务。

 

 

CyclicBarrier

CyclicBarrier简介

CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier),它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,它也是AQS多线程同步操作的一个具体实现。

CountDownLatch和CyclicBarrier区别与原理(图解)-mikechen

CyclicBarrier的实现原理

而 CyclicBarrier 基于 Condition 来实现的,在CyclicBarrier类的内部有一个计数器,每个线程在到达屏障点的时候都会调用await方法将自己阻塞,此时计数器会减1,当计数器减为0的时候所有因调用await方法而被阻塞的线程将被唤醒。

如下图所示:

CountDownLatch和CyclicBarrier区别与原理(图解)-mikechen

 

CountDownLatch和CyclicBarrier区别

  • CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()方法重置,CyclicBarrier 可以循环利用;
  • CountDownLatch 的计数是减 1 直到 0,CyclicBarrier 是加 1,直到指定值。
  • CountDownLatch 是一个线程等待其他线程, CyclicBarrier 是多个线程互相等待;
  • CountDownLatch会阻塞主线程,CyclicBarrier不会阻塞主线程,只会阻塞子线程;
  • CountDownLatch 放行由其他线程控制而CyclicBarrier是由本身来控制的。

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法