CyclicBarrier的底层实现

想了解CyclicBarrier的底层实现,你可以先去考虑2个问题。

  • 一个是需求是什么?
  • 第二个是CyclicBarrier可以直接使用AQS来实现吗?

从这个维度出发去思考,能更好的理解CyclicBarrier的底层实现。

同时这个也是一个设计的问题,开发CyclicBarrier的人当时到底是基于什么样的想法来实现的。

在真正开始之前,建议先翻看一下我之前写的关于CyclicBarrier和CountDownLatch 的文章,是一个系列的文章来的,理解之前的这些文章,对阅读本文很有帮助。

好。我们现在开始先说需求:

我们想分批地处理任务,在每一个批次内部,使用多线程并发的方式来提升处理性能。同时,这个分批处理的过程是可循环的,即处理完一批后自动进入下一批,持续执行下去。 这里有一个核心问题:必须保证当前批次内所有并发线程都执行完毕后,才能开始处理下一个批次。也就是说,需要一个同步机制,让所有参与当前批次的线程互相等待,直到最后一个线程也完成,再统一放行进入下一批的处理。

注意这里的描述,有几个关键词:

  • 分批,也即是任务按照批次划分;
  • 一个分批内必须并发;
  • 分批与分批之间必须同步;
  • 最后一个是循环;

既然是一个需求,那么各种技术语言里,应该都有对应的实现方案。

比如:

  • Java:CyclicBarrier;
  • Python:threading.Barrier;
  • C++:std::barrier
  • 。。。。等等。。。。

既然需求清楚了,我们就来看看Java中CyclicBarrier中的实现方案。

首先想到的是,能不能直接使用AQS呢? 毕竟能复用的就复用,且AQS已经是非常成熟的方案了。

答案是不行的,因为两者的「并发语义」是不太匹配的。

AQS的核心模型是:独占或者共享资源的获取与释放,简单讲就是是一个竞争模型,多个线程争抢有限资源。

而CyclicBarrier如上面需求说的,要应付的是协作相互等待,多个线程到达后,不存在谁抢到谁先执行的问题。

但是我们也不能说直接用Java手写一个,还是可以记住Java里提供的一些基础类的。

那哪些类跟CyclicBarrier的需求是匹配的呢? 就是ReentrantLock + Condition。

因为这两个类精确的对应了CyclicBarrier的核心动作:

  • ReentrantLock确保批次内所有任务都完成:因此这里是有计数的动作的,需要线程安全的减一,直到变成0(这里是有判断是否为0的动作的)为止;
  • Condition实现批次完成后统一放行:当计数减到0后,需要一次性唤醒所有之前等待的线程;没到齐时,当前线程要挂起等待;

ReentrantLock提供了轻量级的互斥保护,保证同一时刻只有一个线程在修改count并做判断,既安全又高效。

而Condition原生提供await()(挂起)和signalAll()(批量唤醒)。

好,我们用一个表格来完整列一下为啥ReentrantLock + Condition是实现的CyclicBarrier的完美组合。

CyclicBarrier 的需求 ReentrantLock + Condition 的能力 匹配度
多线程安全修改count Lock提供互斥临界区 完美
未凑齐时挂起当前线程 Condition.await() 完美
凑齐后批量唤醒所有线程 Condition.signalAll() 完美
支持超时等待 / 中断响应 Condition.await(timeout) / awaitUninterruptibly 完美
每轮结束后重置状态,进入下一轮 Lock保护下重置count,Condition自动复用 完美
可循环使用 Lock + Condition 本身无状态,重置count即可复用 完美

而直接使用AQS来解决这种周期性批量唤醒是很难搞的,或者说,搞不了。

好,下面我留一个思考题:

就是可以使用CAS或者synchronized去替换ReentrantLock?

相关推荐
god_cvz1 小时前
第二章:6、对话记忆与引用标注
后端·ai编程
拖孩1 小时前
全程 AI 写的小程序,刚接上会员虚拟支付,上线第二天就有人真金白银买单了|双签名、定价、iOS 的坑我全踩了一遍
前端·后端·微信小程序
我是人✓1 小时前
SpringMVC异常处理与拦截器实战揭秘
java·开发语言·后端
仟里码1 小时前
九:goroutine(1.什么是协程)
后端
不是万能的豆学长1 小时前
排查Go服务40天后的内存泄漏问题
开发语言·后端·golang·go
ShineWinsu1 小时前
对于HTML:HTML常见标签的解析—上
前端·面试·html·浏览器·标签·图片·超链接
阿狗童鞋1 小时前
SpringSecurity权限认证实战指南
java·后端·spring
韩振方1 小时前
Kubernetes Service 让会更换的 Pod 有稳定访问入口
后端
用户125758524361 小时前
Golang后台管理框架推荐:XYGo Admin与devinggo怎么选?
后端·go·ai编程