资讯动态

CyclicBarrier的底层实现

发布时间:2026/10/14 17:06:00 来源:尧图企业网站定制
想了解CyclicBarrier的底层实现你可以先去考虑2个问题。一个是需求是什么?第二个是CyclicBarrier可以直接使用AQS来实现吗?从这个维度出发去思考能更好的理解CyclicBarrier的底层实现。同时这个也是一个设计的问题开发CyclicBarrier的人当时到底是基于什么样的想法来实现的。在真正开始之前建议先翻看一下我之前写的关于CyclicBarrier和CountDownLatch 的文章是一个系列的文章来的理解之前的这些文章对阅读本文很有帮助。好。我们现在开始先说需求我们想分批地处理任务在每一个批次内部使用多线程并发的方式来提升处理性能。同时这个分批处理的过程是可循环的即处理完一批后自动进入下一批持续执行下去。这里有一个核心问题必须保证当前批次内所有并发线程都执行完毕后才能开始处理下一个批次。也就是说需要一个同步机制让所有参与当前批次的线程互相等待直到最后一个线程也完成再统一放行进入下一批的处理。注意这里的描述有几个关键词分批也即是任务按照批次划分一个分批内必须并发分批与分批之间必须同步最后一个是循环既然是一个需求那么各种技术语言里应该都有对应的实现方案。比如JavaCyclicBarrierPythonthreading.BarrierCstd::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 的能力匹配度多线程安全修改countLock提供互斥临界区完美未凑齐时挂起当前线程Condition.await()完美凑齐后批量唤醒所有线程Condition.signalAll()完美支持超时等待 / 中断响应Condition.await(timeout) / awaitUninterruptibly完美每轮结束后重置状态进入下一轮Lock保护下重置countCondition自动复用完美可循环使用Lock Condition 本身无状态重置count即可复用完美而直接使用AQS来解决这种周期性批量唤醒是很难搞的或者说搞不了。好下面我留一个思考题就是可以使用CAS或者synchronized去替换ReentrantLock?

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑