同步工具类CyclicBarrier原理及使用

简介

  • 栅栏类似于闭锁,它能阻塞一组线程直到某个事件的发生。栅栏与闭锁的关键区别在于,所有的线程必须同时到达栅栏位置,才能继续执行。闭锁用于等待事件,而栅栏用于等待其他线程。

  • CyclicBarrier可以使一定数量的线程反复地在栅栏位置处汇集。当线程到达栅栏位置时将调用await方法,这个方法将阻塞直到所有线程都到达栅栏位置。如果所有线程都到达栅栏位置,那么栅栏将打开,此时所有的线程都将被释放,而栅栏将被重置以便下次使用。

概念解释

  • 屏障
指定数量的线程全部调用 cyclicBarrier的await()方法时,这些线程不再阻塞
复制代码
  • 循环
通过reset()方法可以进行重置
复制代码

初始化屏障方式

  • 方式一
public CyclicBarrier(int parties)
复制代码
  • 方式二
 public CyclicBarrier(int parties, Runnable barrierAction)
 
 设置屏障打开前首先运行的线程即该线程的执行时机是在到达屏障之后再执行
复制代码

典型案例

CyclicBarrier-循环屏障-模拟多线程计算

需求
1、初始化50000条数据
2、通过5个线程并行处理 每一个线程分别处理10000条数据(通过线程池中的5个线程处理)
3、然后将5个线程分别的处理结果汇总(通过初始化栅栏的时候第二个构造函数定义的那个线程处理即Runnable barrierAction)
复制代码
代码实现及过程分析
形象解释

方法介绍

是否被破坏

isBroken()

默认为true

状态被改变的场景:
 1.等待线程被interrupt 2.等待线程timeout 3、其他线程调用reset(),将其重置为true 复制代码

获取开启屏障的方数

barrier.getParties()
复制代码

获取正在等待的线程数

barrier.getNumberWaiting()
复制代码

向栅栏”报道“

  • await()
形象的理解:每有一个线程达到栅栏,就会向栅栏报道,等到齐了指定人数,栅栏就会打开,让这些数量的线程通过

该状态被终止的场景:
1.屏障打开
2.本线程被interrupt
3.其他等待线程被interrupted 4.其他等待线程timeout 5.其他线程调用reset()  复制代码
  • await(timeout,TimeUnit)
该状态被终止的场景:

1.屏障打开(返回true)
2.本线程被interrupt
3.本线程timeout
4.其他等待线程被interrupted 5.其他等待线程timeout 6.其他线程调用reset() 复制代码

重置

reset()

将CyclicBarrier回归初始状态,如果有正在等待的线程,则会抛出BrokenBarrierException异常
复制代码

比较

CyclicBarrier 线程相互等待 可以重置count
CountDownLatch 当前线程等待一个或多个线程 count=0,不可重置

源码分析

核心源码

await方法
复制代码
同时,Generation描述着CyclicBarrier的更新换代。在CyclicBarrier中,同一批线程属于同一代。当有parties个线程到达barrier之后,generation就会被更新换代。其中broken标识该当前CyclicBarrier是否已经处于中断状态。
复制代码
默认barrier是没有损坏的。当barrier损坏了或者有一个线程中断了,则通过breakBarrier()来终止所有的线程
复制代码

源码核心技术点

ReentrantLock

这里先简单介绍下和synchronized区别 下一节再详细的说下

(1)synchronized是独占锁,加锁和解锁的过程自动进行,易于操作,但不够灵活。ReentrantLock也是独占锁,加锁和解锁的过程需要手动进行,不易操作,但非常灵活。

(2)synchronized可重入,因为加锁和解锁自动进行,不必担心最后是否释放锁;ReentrantLock也可重入,但加锁和解锁需要手动进行,且次数需一样,否则其他线程无法获得锁。
 (3)synchronized不可响应中断,一个线程获取不到锁就一直等着;ReentrantLock可以相应中断。  (4)ReentrantLock还可以实现公平锁机制 通俗的理解就是谁排队时间最长谁先执行获取锁 复制代码

代码资源

https://gitee.com/pingfanrenbiji/myconcurrent/blob/master/src/main/java/pers/hanchao/concurrent/eg15/CyclicBarrierDemo.java
复制代码

参考文章

https://blog.csdn.net/qq_38293564/article/details/80558157
https://baijiahao.baidu.com/s?id=1648624077736116382&wfr=spider&for=pc
复制代码

本文使用 mdnice 排版

猜你喜欢

转载自juejin.im/post/5eeadaece51d4573d5598829