Java并发:倒计时锁存器与循环屏障

问题

我正在阅读java.util.concurrent API,并发现了

  • CountDownLatch:允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。
  • CyclicBarrier:一种同步辅助工具,允许一组线程全部等待彼此到达公共障碍点。

对我来说,两者似乎都是平等的,但我相信还有更多的东西。

例如,inCoundownLatch, the countdown value could not be reset, that can happen in the case of CyclicBarrier

这两者之间还有其他区别吗?
什么是use cases,有人想要重置倒计时的价值?


#1 热门回答(112 赞)

一个主要区别是CyclicBarrier执行(可选)Runnable任务,该任务在满足公共屏障条件后运行。

它还允许你获取在屏障处等待的客户端数量以及触发屏障所需的数量。一旦触发,屏障就会重置并可以再次使用。

对于简单的用例 - 服务启动等... CountdownLatch很好。 CyclicBarrier对于更复杂的协调任务非常有用。这种事情的一个例子是并行计算 - 计算中涉及多个子任务 - 类似于MapReduce


#2 热门回答(108 赞)

还有另外一个区别。

使用aCyclicBarrier时,假设你指定触发屏障的等待线程数。如果指定5,则必须至少有5个线程才能调用await()

使用aCountDownLatch时,指定将调用countDown()的调用次数,这将导致所有等待线程被释放。这意味着你只能使用一个线程使用aCountDownLatch

"你为什么要那样做?",你可能会说。想象一下,你正在使用由执行回调的其他人编码的神秘API。你希望其中一个线程等待多次调用某个回调。你不知道将调用哪个回调函数。在这种情况下,aCountDownLatch是完美的,而我想不出任何方法来实现这个使用aCyclicBarrier(实际上,我可以,但它涉及超时......哎呀!)。

我只是希望CountDownLatch可以重置!


#3 热门回答(33 赞)

没有人提到的一点是,在aCyclicBarrier中,如果一个线程有问题(超时,中断......),所有其他已达到await()的其他例外。见Javadoc:

CyclicBarrier使用全部或全部破坏模型进行失败的同步尝试:如果线程因中断,失败或超时而过早地离开障碍点,则在该障碍点等待的所有其他线程也将通过BrokenBarrierException异常地离开(或者InterruptedException如果它们也在大约同一时间被中断)。