Java CountDownLatch 与信号量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/184147/
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
CountDownLatch vs. Semaphore
提问by finnw
Is there any advantage of using
使用有什么好处吗
java.util.concurrent.CountdownLatch
java.util.concurrent.CountdownLatch
instead of
代替
java.util.concurrent.Semaphore?
java.util.concurrent.Semaphore?
As far as I can tell the following fragments are almost equivalent:
据我所知,以下片段几乎是等效的:
1. Semaphore
1. 信号量
final Semaphore sem = new Semaphore(0);
for (int i = 0; i < num_threads; ++ i)
{
Thread t = new Thread() {
public void run()
{
try
{
doStuff();
}
finally
{
sem.release();
}
}
};
t.start();
}
sem.acquire(num_threads);
2: CountDownLatch
2:倒计时锁存器
final CountDownLatch latch = new CountDownLatch(num_threads);
for (int i = 0; i < num_threads; ++ i)
{
Thread t = new Thread() {
public void run()
{
try
{
doStuff();
}
finally
{
latch.countDown();
}
}
};
t.start();
}
latch.await();
Except that in case #2 the latch cannot be reused and more importantly you need to know in advance how many threads will be created (or wait until they are all started before creating the latch.)
除了在 #2 的情况下,闩锁不能被重用,更重要的是,您需要提前知道将创建多少线程(或等到它们全部启动后再创建闩锁。)
So in what situation might the latch be preferable?
那么在什么情况下闩锁更可取呢?
采纳答案by James Schek
CountDown latch is frequently used for the exact opposite of your example. Generally, you would have many threads blocking on "await()" that would all start simultaneously when the countown reached zero.
CountDown 锁存器经常用于与您的示例完全相反的情况。通常,当计数达到零时,您会在“await()”上阻塞许多线程,这些线程都会同时启动。
final CountDownLatch countdown = new CountDownLatch(1);
for (int i = 0; i < 10; ++ i){
Thread racecar = new Thread() {
public void run() {
countdown.await(); //all threads waiting
System.out.println("Vroom!");
}
};
racecar.start();
}
System.out.println("Go");
countdown.countDown(); //all threads start now!
You could also use this as an MPI-style "barrier" that causes all threads to wait for other threads to catch up to a certain point before proceeding.
您还可以将其用作 MPI 样式的“屏障”,使所有线程在继续之前等待其他线程赶上某个点。
final CountDownLatch countdown = new CountDownLatch(num_thread);
for (int i = 0; i < num_thread; ++ i){
Thread t= new Thread() {
public void run() {
doSomething();
countdown.countDown();
System.out.printf("Waiting on %d other threads.",countdown.getCount());
countdown.await(); //waits until everyone reaches this point
finish();
}
};
t.start();
}
That all said, the CountDown latch can safely be used in the manner you've shown in your example.
话虽如此,倒计时锁存器可以安全地以您在示例中显示的方式使用。
回答by Spencer Kormos
CountdownLatch makes threads wait on the await()
method, until such a time as the count has reached zero. So maybe you want all your threads to wait until 3 invocations of something, then all the threads can go. A Latch generally can not be reset.
CountdownLatch 使线程等待该await()
方法,直到计数达到零为止。因此,也许您希望所有线程都等待 3 次调用某事,然后所有线程都可以运行。A Latch 一般不能复位。
A Semaphore allows threads to retrieve permits, which prevents too many threads from executing at once, blocking if it cannot get the permit(s) it requires to proceed. Permits can be returned to a Semaphore allowing the other waiting threads to proceed.
信号量允许线程检索许可,这可以防止过多的线程同时执行,如果无法获得继续执行所需的许可就会阻塞。许可可以返回给信号量,允许其他等待的线程继续进行。
回答by Tom Hawtin - tackline
Looking at the freely available source, there is no magic in the implementation of the two classes, so their performance should be much the same. Choose the one that makes your intent more obvious.
查看免费提供的源代码,这两个类的实现没有什么神奇之处,因此它们的性能应该大同小异。选择使您的意图更加明显的一种。
回答by mtruesdell
CountDownLatchis used to start a series of threads and then wait until all of them are complete (or until they call countDown()
a given number of times.
CountDownLatch用于启动一系列线程,然后等待所有线程完成(或直到它们调用countDown()
给定次数。
Semaphore is used to control the number of concurrent threads that are using a resource. That resource can be something like a file, or could be the cpu by limiting the number of threads executing. The count on a Semaphore can go up and down as different threads call acquire()
and release()
.
信号量用于控制使用资源的并发线程数。该资源可以是文件之类的东西,也可以是限制执行线程数的 cpu。随着不同线程调用acquire()
和 ,信号量的计数可以上下波动release()
。
In your example, you're essentially using Semaphore as a sort of CountUPLatch. Given that your intent is to wait on all threads finishing, using the CountdownLatch
makes your intention clearer.
在您的示例中,您本质上是将信号量用作一种 Count UPLatch。鉴于您的意图是等待所有线程完成,使用CountdownLatch
使您的意图更清晰。
回答by Raj Srinivas
Say you walked in to golf pro shop, hoping to find a foursome,
假设你走进高尔夫专卖店,希望找到一个四人组,
When you stand in line to get a tee time from one of the pro shop attendants, essentially you called proshopVendorSemaphore.acquire()
, once you get a tee time, you called proshopVendorSemaphore.release()
.Note: any of the free attendants can service you, i.e. shared resource.
当您排队从其中一位专卖店服务员那里获得开球时间时,本质上是您打了电话proshopVendorSemaphore.acquire()
,一旦您到了开球时间,您proshopVendorSemaphore.release()
就打了电话。注意:任何免费服务员都可以为您服务,即共享资源。
Now you walk up to starter, he starts a CountDownLatch(4)
and calls await()
to wait for others, for your part you called checked-in i.e. CountDownLatch
.countDown()
and so does rest of the foursome. When all arrive, starter gives go ahead(await()
call returns)
现在你走到 starter ,他开始 aCountDownLatch(4)
并打电话await()
等待其他人,对于你来说,你称之为 check-in ie CountDownLatch
。countDown()
四人组的其余部分也是如此。全部到达后,starter 继续执行(await()
调用返回)
Now, after nine holes when each of you take a break, hypothetically lets involve starter again, he uses a 'new' CountDownLatch(4)
to tee off Hole 10, same wait/sync as Hole 1.
现在,在 9 洞之后,当你们每个人都休息时,假设让CountDownLatch(4)
发球手再次参与,他使用“新”开球第 10 洞,与第 1 洞相同的等待/同步。
However, if the starter used a CyclicBarrier
to begin with, he could have reset the same instance in Hole 10 instead of a second latch, which use & throw.
但是,如果起始者使用 aCyclicBarrier
开始,他可以在第 10 洞重置相同的实例,而不是使用 & throw 的第二个闩锁。
回答by Ravindra babu
Short summary:
简短的摘要:
Semaphoreand CountDownLatchserves different purpose.
Use Semaphoreto control thread access to resource.
Use CountDownLatchto wait for completion of all threads
Semaphore和CountDownLatch用于不同的目的。
使用信号量来控制线程对资源的访问。
使用CountDownLatch等待所有线程完成
Semaphoredefinition from javadocs:
javadocs 中的信号量定义:
A Semaphoremaintains a set of permits. Each acquire()blocks if necessary until a permitis available, and then takes it. Each release()adds a permit, potentially releasing a blocking acquirer.
一个信号灯维护一组允许的。如有必要,每个acquire() 都会阻塞,直到获得许可为止,然后获取它。每个release()添加一个许可,可能会释放一个阻塞的获取者。
However, no actual permit objects are used; the Semaphorejust keeps a count of the number available and acts accordingly.
但是,没有使用实际的许可对象;该信号量只是不断数量的计数可用,采取相应的行动。
How does it work ?
它是如何工作的 ?
Semaphores are used to control the number of concurrent threads that are using a resource.That resource can be something like a shared data, or a block of code (critical section) or any file.
信号量用于控制使用资源的并发线程数。资源可以是共享数据、代码块(临界区)或任何文件。
The count on a Semaphore can go up and down as different threads call acquire
() and release
(). But at any point of time, you can't have more number of threads greater than Semaphore count.
当不同的线程调用acquire
() 和release
()时,信号量的计数可以上下波动。但是在任何时候,线程数都不能超过信号量计数。
Semaphore Use cases:
信号量用例:
- Limiting concurrent access to disk (this can kill performance due to competing disk seeks)
- Thread creation limiting
- JDBC connection pooling / limiting
- Network connection throttling
- Throttling CPU or memory intensive tasks
- 限制对磁盘的并发访问(这会由于竞争磁盘寻道而降低性能)
- 线程创建限制
- JDBC 连接池/限制
- 网络连接限制
- 限制 CPU 或内存密集型任务
Have a look at this articlefor semaphore uses.
有关信号量的使用,请查看本文。
CountDownLatchdefinition from javadocs:
来自 javadocs 的CountDownLatch定义:
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
一种同步辅助,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。
How does it work?
它是如何工作的?
CountDownLatchworks by having a counter initialized with number of threads, which is decremented each time a thread complete its execution. When count reaches to zero, it means all threads have completed their execution, and thread waiting on latch resume the execution.
CountDownLatch 的工作原理是使用线程数初始化计数器,每次线程完成执行时该计数器都会递减。当计数为零时,表示所有线程都已完成执行,等待闩锁的线程继续执行。
CountDownLatch Use cases:
CountDownLatch 用例:
- Achieving Maximum Parallelism: Sometimes we want to start a number of threads at the same time to achieve maximum parallelism
- Wait N threads to completes before start execution
- Deadlock detection.
- Achieving Maximum Parallelism:有时我们想同时启动多个线程来实现最大并行度
- 在开始执行之前等待 N 个线程完成
- 死锁检测。
Have a look at this articleto understand CountDownLatch concepts clearly.
看看这篇文章可以清楚地理解 CountDownLatch 的概念。
Have a look at Fork Join Poolat this articletoo. It has some similarities to CountDownLatch.
也可以在这篇文章中查看Fork Join Pool。它与CountDownLatch有一些相似之处。