java CyclicBarrier在集合点的同步

是什么?为什么?怎么做?

 

一、是什么

CyclicBarrier是java.util.concurrent包提供的一个同步辅助类,它允许一组线程互相等待,直到所有线程都到达某个公共屏障点。

CyclicBarrier主要用于一组固定大小的线程之间,每条线程之间相互等待,当所有线程都完成某项任务之后,才能执行之后的任务。

例如:几个运动员组织了一次赛跑,但是没有裁判。所以他们约定好,每个人各自做好起跑准备,同时也等待其他人也做好起跑准备。等所有人都做好准备后,大家同时出发。

这个场景有两个特点:

1.运动员需要互相等待直到所有人都做好准备(线程之间互相等待至某个时间点)。

2.所有人做好准备后,同时出发(所有线程都到达时间点后,自身继续执行下去)。

二、为什么

1.为什么使用CyclicBarrier

使用CyclicBarrier的原因主要是场景决定的,具体情况需要具体分析。参考上篇文章:

java CountDownLatch等待多个并发事件的完成

上次的场景适合使用CountDownLatch,这次的场景适合使用CyclicBarrier。

为什么使用CyclicBarrier?就是因为CyclicBarrier足够安全好用。如果要自己实现同样的功能,不仅低效,而且容易引发问题。在上面的赛跑场景中,应该没有什么比使用CyclicBarrier更好的解决方案了。

2.CyclicBarrier和CountDownLatch的一些区别

(1)适用的场景不同

CyclicBarrier适合一些线程需要相互等待,同时并发的情景。

CountDownLatch适合线程之间存在先后执行的顺序关系的情景。

(2)CountDownLatch不可重复使用,CyclicBarrier可以

如果写在一个循环中(比如while或者for),CyclicBarrier可以重复使用(栅栏打开之后会重新关闭,CyclicBarrier对象可以一直使用),而CountDownLatch是一次性的(计数器到达0的时候就失效了)。

(3)实现原理不同

这里不展开讨论了。

三、怎么做

继续使用上面的例子:

几个运动员组织了一次赛跑,但是没有裁判。所以他们约定好,每个人各自做好起跑准备,同时也等待其他人也做好起跑准备。等所有人都做好准备后,大家同时出发。

我的思路:

顾名思义,CyclicBarrier是一个循环栅栏。当所有运动员都准备完成了,那么栅栏就会打开,所有运动员同时出发,然后栅栏放下。在下一个循环过程中,栅栏可以继续使用。

首先自定义一个CyclicBarrier对象:

直到三条线程到达等待状态,栅栏才会打开。当线程执行到:

时,就会进入等待状态。如果正在等待的线程已经到达了3条,那么栅栏就会打开,所有处于等待状态中的线程将同时继续执行(表现为所有运动员同时起跑)。

运行结果为:

为了体现CyclicBarrier可以循环,改造一下main方法,使用同一栅栏,模仿三次比赛的进行:

结果符合期望,可以成功模拟。这就说明栅栏具备开合功能,CyclicBarrier可以循环使用。

四、总结

具体情况具体分析,要在最适合的时候使用CyclicBarrier。

发表评论

电子邮件地址不会被公开。 必填项已用*标注