Java 并发:倒计时闩锁与循环屏障
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4168772/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java concurrency: Countdown latch vs Cyclic barrier
提问by daydreamer
I was reading through the java.util.concurrent API, and found that
我正在阅读java.util.concurrent API,发现
CountDownLatch
: A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.CyclicBarrier
: A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
CountDownLatch
:一种同步辅助,允许一个或多个线程等待,直到其他线程中正在执行的一组操作完成。CyclicBarrier
: 一种同步辅助,允许一组线程全部等待彼此到达公共屏障点。
To me both seems equal, but I am sure there is much more to it.
对我来说两者似乎是平等的,但我相信还有更多。
For example, in CoundownLatch, the countdown value could not be reset, that can happen in the case of CyclicBarrier
.
例如,在CoundownLatch, the countdown value could not be reset, that can happen in the case of CyclicBarrier
.
Is there any other difference between the two?
What are the use cases
where someone would want to reset the value of countdown?
两者之间还有其他区别吗?
有什么use cases
地方会有人想重置倒计时的价值?
采纳答案by Jon
One major difference is that CyclicBarriertakes an (optional) Runnable task which is run once the common barrier condition is met.
一个主要区别是CyclicBarrier接受一个(可选的)Runnable 任务,一旦满足公共障碍条件就会运行该任务。
It also allows you to get the number of clients waiting at the barrier and the number required to trigger the barrier. Once triggered the barrier is reset and can be used again.
它还允许您获取在屏障处等待的客户端数量以及触发屏障所需的数量。一旦触发,屏障就会重置并可以再次使用。
For simple use cases - services starting etc... a CountdownLatch is fine. A CyclicBarrier is useful for more complex co-ordination tasks. An example of such a thing would be parallel computation - where multiple subtasks are involved in the computation - kind of like MapReduce.
对于简单的用例 - 服务启动等...... CountdownLatch 很好。CyclicBarrier 对于更复杂的协调任务很有用。这种事情的一个例子是并行计算 - 计算中涉及多个子任务 - 有点像MapReduce。
回答by JohnnyO
The main difference is documented right in the Javadocs for CountdownLatch. Namely:
主要区别记录在 CountdownLatch 的 Javadocs 中。即:
A CountDownLatch is initialized with a given count. The await methods block until the current count reaches zero due to invocations of the countDown() method, after which all waiting threads are released and any subsequent invocations of await return immediately. This is a one-shot phenomenon -- the count cannot be reset. If you need a version that resets the count, consider using a CyclicBarrier.
CountDownLatch 使用给定的计数进行初始化。由于调用了 countDown() 方法,await 方法会阻塞直到当前计数达到零,之后所有等待线程都被释放,任何后续的 await 调用都会立即返回。这是一种一次性现象——计数无法重置。如果您需要重置计数的版本,请考虑使用 CyclicBarrier。
source 1.6 Javadoc
回答by Kim
There's another difference.
还有一个区别。
When using a CyclicBarrier
, the assumption is that you specify the number of waiting threads that trigger the barrier. If you specify 5, you must have at least 5 threads to call await()
.
使用 a 时CyclicBarrier
,假设您指定触发屏障的等待线程数。如果指定 5,则必须至少有 5 个线程来调用await()
。
When using a CountDownLatch
, you specify the number of calls to countDown()
that will result in all waiting threads being released. This means that you can use a CountDownLatch
with only a single thread.
使用 a 时CountDownLatch
,您指定countDown()
将导致所有等待线程被释放的调用次数。这意味着您只能使用一个CountDownLatch
线程。
"Why would you do that?", you may say. Imagine that you are using a mysterious API coded by someone else that performs callbacks. You want one of your threads to wait until a certain callback has been called a number of times. You have no idea which threads the callback will be called on. In this case, a CountDownLatch
is perfect, whereas I can't think of any way to implement this using a CyclicBarrier
(actually, I can, but it involves timeouts... yuck!).
“你为什么要这样做?”,你可能会说。想象一下,您正在使用由其他人编写的神秘 API 来执行回调。您希望您的一个线程等待某个回调被多次调用。您不知道将在哪些线程上调用回调。在这种情况下, aCountDownLatch
是完美的,而我想不出任何使用 a 来实现它的方法CyclicBarrier
(实际上,我可以,但它涉及超时......糟糕!)。
I just wish that CountDownLatch
could be reset!
我只是希望CountDownLatch
可以重置!
回答by Brandon
In the case of CyclicBarrier, as soon as ALL child threads begins calling barrier.await(), the Runnable is executed in the Barrier. The barrier.await in each child thread will take different lengh of time to finish, and they all finish at the same time.
在 CyclicBarrier 的情况下,一旦所有子线程开始调用 barrier.await(),Runnable 就会在 Barrier 中执行。每个子线程中的barrier.await 需要不同的时间来完成,并且它们都是同时完成的。
回答by shams
A CountDownLatch is used for one-time synchronization. While using a CountDownLatch, any thread is allowed to call countDown() as many times as they like. Threads which called await() are blocked until the count reaches zero because of calls to countDown() by other unblocked threads. The javadoc for CountDownLatchstates:
CountDownLatch 用于一次性同步。在使用 CountDownLatch 时,任何线程都可以根据需要多次调用 countDown()。由于其他未阻塞线程对 countDown() 的调用,调用 await() 的线程将被阻塞,直到计数达到零。CountDownLatch的javadoc指出:
The await methods block until the current count reaches zero due to invocations of the countDown() method, after which all waiting threads are released and any subsequent invocations of await return immediately. ...
Another typical usage would be to divide a problem into N parts, describe each part with a Runnable that executes that portion and counts down on the latch, and queue all the Runnables to an Executor. When all sub-parts are complete, the coordinating thread will be able to pass through await. (When threads must repeatedly count down in this way, instead use a CyclicBarrier.)
由于调用了 countDown() 方法,await 方法会阻塞直到当前计数达到零,之后所有等待线程都被释放,任何后续的 await 调用都会立即返回。...
另一个典型的用法是将问题分成 N 个部分,用一个 Runnable 描述每个部分,该 Runnable 执行该部分并在闩锁上倒计时,并将所有 Runnable 排到一个 Executor 中。当所有子部分完成后,协调线程将能够通过await。(当线程必须以这种方式重复倒计时时,请使用 CyclicBarrier。)
In contrast, the cyclic barrier is used for multiple sychronization points, e.g. if a set of threads are running a loop/phased computation and need to synchronize before starting the next iteration/phase. As per the javadoc for CyclicBarrier:
相比之下,循环屏障用于多个同步点,例如,如果一组线程正在运行循环/分阶段计算并且需要在开始下一个迭代/阶段之前进行同步。根据CyclicBarrier的javadoc:
The barrier is called cyclic because it can be re-used after the waiting threads are released.
屏障被称为循环的,因为它可以在等待线程被释放后重新使用。
Unlike the CountDownLatch, each call to await() belongs to some phase and can cause the thread to block until all parties belonging to that phase have invoked await(). There is no explicit countDown() operation supported by the CyclicBarrier.
与 CountDownLatch 不同的是,对 await() 的每次调用都属于某个阶段,并且可能导致线程阻塞,直到属于该阶段的所有各方都调用了 await()。CyclicBarrier 不支持显式 countDown() 操作。
回答by Chirlo
One point that nobody has yet mentioned is that, in a CyclicBarrier
, if a thread has a problem (timeout, interrupted...), all the others that have reached await()
get an exception. See Javadoc:
没有人提到的一点是,在 a 中CyclicBarrier
,如果一个线程有问题(超时、中断...),所有其他已经到达的线程await()
都会出现异常。见Javadoc:
The CyclicBarrier uses an all-or-none breakage model for failed synchronization attempts: If a thread leaves a barrier point prematurely because of interruption, failure, or timeout, all other threads waiting at that barrier point will also leave abnormally via BrokenBarrierException (or InterruptedException if they too were interrupted at about the same time).
CyclicBarrier 对失败的同步尝试使用全有或无中断模型:如果一个线程由于中断、失败或超时而过早离开屏障点,则在该屏障点等待的所有其他线程也将通过 BrokenBarrierException(或 InterruptedException)异常离开如果他们也几乎同时被打断)。
回答by Kevin Lee
This question has been adequately answered already, but I think I can value-add a little by posting some code.
这个问题已经得到了充分的回答,但我认为我可以通过发布一些代码来增加一点价值。
To illustrate the behaviour of cyclic barrier, I have made some sample code. As soon as the barrier is tipped, it is automaticallyreset so that it can be used again (hence it is "cyclic"). When you run the program, observe that the print outs "Let's play" are triggered only after the barrier is tipped.
为了说明循环屏障的行为,我制作了一些示例代码。一旦障碍物倾斜,它会自动重置,以便可以再次使用(因此它是“循环的”)。当您运行程序时,请注意只有在障碍物倾斜后才会触发打印输出“Let's play”。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierCycles {
static CyclicBarrier barrier;
public static void main(String[] args) throws InterruptedException {
barrier = new CyclicBarrier(3);
new Worker().start();
Thread.sleep(1000);
new Worker().start();
Thread.sleep(1000);
new Worker().start();
Thread.sleep(1000);
System.out.println("Barrier automatically resets.");
new Worker().start();
Thread.sleep(1000);
new Worker().start();
Thread.sleep(1000);
new Worker().start();
}
}
class Worker extends Thread {
@Override
public void run() {
try {
CyclicBarrierCycles.barrier.await();
System.out.println("Let's play.");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
回答by Justin Civi
I think that the JavaDoc has explained the differences explicitly. Most people know that CountDownLatch can not be reset, however, CyclicBarrier can. But this is not the only difference, or the CyclicBarrier could be renamed to ResetbleCountDownLatch. We should tell the differences from the perspective of their goals, which are described in JavaDoc
我认为 JavaDoc 已经明确解释了这些差异。大多数人都知道 CountDownLatch 不能重置,但是 CyclicBarrier 可以。但这并不是唯一的区别,或者可以将 CyclicBarrier 重命名为 ResetbleCountDownLatch。我们应该从他们的目标的角度来区分差异,JavaDoc 中有描述
CountDownLatch:A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
CountDownLatch:一种同步辅助工具,它允许一个或多个线程等待其他线程中正在执行的一组操作完成。
CyclicBarrier:A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
CyclicBarrier:一种同步辅助工具,它允许一组线程相互等待,以达到共同的障碍点。
In countDownLatch, there is one or more threads, that are waiting for a set of other threadsto complete. In this situation, there are two types of threads, one type is waiting, another type is doing something, after finishes their tasks, they could be waiting or just terminated.
在 countDownLatch 中,有一个或多个线程正在等待一组其他线程完成。在这种情况下,有两种类型的线程,一种是等待,另一种是做某事,完成任务后,它们可能是等待或只是终止。
In CyclicBarrier, there are only one type of threads, they are waiting for each other, they are equal.
在 CyclicBarrier 中,只有一种线程,它们相互等待,它们是平等的。
回答by Pramma
One obvious difference is, only N threads can await on a CyclicBarrier of N to be release in one cycle. But unlimited number of threads can await on a CountDownLatch of N. The count down decrement can be done by one thread N times or N threads one time each or combinations.
一个明显的区别是,只有 N 个线程可以等待 N 的 CyclicBarrier 在一个周期内被释放。但是无限数量的线程可以等待 N 的 CountDownLatch。倒计时递减可以由一个线程 N 次或 N 个线程每次或组合完成。
回答by V Jo
In CountDownLatch, main threads waits for other threads to complete their execution. In CyclicBarrier, worker threads wait for each other to complete their execution.
在CountDownLatch 中,主线程等待其他线程完成它们的执行。在CyclicBarrier 中,工作线程相互等待以完成它们的执行。
You can not reuse same CountDownLatchinstance once count reaches to zero and latch is open, on the other hand CyclicBarriercan be reused by resetting Barrier, Once barrier is broken.
一旦计数达到零并且闩锁打开,您就不能重用相同的CountDownLatch实例,另一方面,一旦屏障被破坏,可以通过重置屏障来重用CyclicBarrier。