CountDownLatch 与信号量
使用
java.util.concurrent.CountDownLatch.html 是否有任何优势? util.concurrent.CountdownLatch
而不是
java.util.concurrent.Semaphore?
据我所知,以下片段几乎是等效的:
1. Semaphore
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
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();
除了第二种情况,锁存器不能重用,更重要的是你需要提前知道将创建多少个线程(或者等到它们全部启动后再使用)创建闩锁。)
那么在什么情况下闩锁可能更可取呢?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
CountDownLatch 用于启动一系列线程,然后等待,直到所有线程完成(或者直到它们调用
countDown()
给定的次数。信号量用于控制正在使用资源的并发线程的数量。该资源可以是文件之类的东西,也可以是通过限制执行线程数量的 CPU。当不同的线程调用
acquire()
和release( 时,信号量的计数可能会上下波动。 )
在您的示例中,您实际上是使用 Semaphore 作为一种 CountUPLatch,因为您的目的是使用
CountdownLatch< 来等待所有线程完成。 /code> 让你的意图更清晰。
CountDownLatch is 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.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()
andrelease()
.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.简短摘要:
信号量
和CountDownLatch
有不同的用途。使用
Semaphore
来控制线程对资源的访问。使用
CountDownLatch
等待所有线程完成信号量 来自 docs.oracle.com :
它是如何工作的?
信号量用于控制访问文件、网络套接字等资源的并发线程数。
信号量使用计数器值进行初始化,该计数器值提供允许的最大许可。
acquire()
将减少许可数量。release()
将增加许可证数量。 在任何时候,都不可能有更多的资源所有者超过允许的许可证数量。当您的资源数量有限时(可能是线程数、网络套接字数、网络打印机数等),它很有用。
Javadocs 中的 CountDownLatch 定义:
它是如何工作的?
CountDownLatch
通过设置一个用线程数初始化的计数器来工作。 当线程完成其执行时,计数器就会递减。 当所有线程完成执行后,计数器将归零。CountDownLatch
使用案例:通过 howtodoinjava.com 作者:Lokesh GuptaShort summary:
Semaphore
andCountDownLatch
serves different purpose.Use
Semaphore
to control thread access to resource.Use
CountDownLatch
to wait for completion of all threadsSemaphore
definition of Semaphore from docs.oracle.com :How does it work?
Semaphores are used to control the number of concurrent threads accessing a resource like a file, network socket etc
Semaphore is initialized with a counter value, which provides maximum permits allowed.
acquire()
will decrease number of permits.release()
will increase number of permits. At any time, its not possible to have more number of resource owners crossing permissible permit count.It is useful when you have limited number of resources - it may be number of threads, network sockets , network printers etc.
CountDownLatch
definition from Javadocs:How does it work?
CountDownLatch
works by setting a counter initialized with number of threads. Counter is decremented when a thread complete its execution. When all threads complete the execution, counter will become zero.CountDownLatch
Use cases: by howtodoinjava.com by Lokesh Gupta假设您走进高尔夫专卖店,希望找到一个四人组,
当您排队等待一位专卖店服务员的开球时间时,实际上您调用了
proshopVendorSemaphore.acquire()
,一次你得到一个开球时间,你调用proshopVendorSemaphore.release()
。注意:任何免费服务员都可以为你服务,即共享资源。现在您走到启动器处,他启动一个
CountDownLatch(4)
并调用await()
等待其他人,对于您称为签入的部分,即CountDownLatch
.countDown()
四人组的其余部分也是如此。 当所有人都到达时,出发者继续前进(await()
call returns)现在,在九个洞之后,当你们每个人休息时,假设让出发者再次参与,他使用“新”
CountDownLatch(4)
开球第 10 洞,与第 1 洞相同的等待/同步。但是,如果发球手使用
CyclicBarrier
开始,他可以在第 1 洞中重置相同的实例10 代替第二个锁存器,它使用 & 扔。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 calledproshopVendorSemaphore.release()
.Note: any of the free attendants can service you, i.e. shared resource.Now you walk up to starter, he starts a
CountDownLatch(4)
and callsawait()
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)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.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.查看免费提供的源代码,这两个类的实现没有什么神奇之处,因此它们的性能应该大致相同。 选择能让您的意图更加明显的一项。
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.
CountdownLatch
使线程等待await()
方法,直到计数达到零。 因此,也许您希望所有线程都等待 3 次调用某项,然后所有线程都可以运行。Latch
通常无法重置。信号量允许线程检索许可,这可以防止同时执行太多线程,如果无法获得继续所需的许可,则会阻塞。 许可可以返回到信号量,允许其他等待线程继续进行。
CountdownLatch
makes threads wait on theawait()
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. ALatch
generally can not be reset.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 aSemaphore
allowing the other waiting threads to proceed.信号量通过使用计数器来控制对共享资源的访问。 如果计数器大于零,则允许访问。 如果为零,则访问被拒绝。 计数器正在计算允许访问共享资源的许可。 因此,要访问资源,线程必须获得信号量的许可。
CountDownlatch 使线程等待,直到发生一个或多个事件。 countDownLatch 最初是通过对锁存器释放之前发生的事件数进行计数来创建的。 每次发生事件时,计数都会递减。
Semaphore controls access to a shared resource through the use of a counter. If the counter is greater than zero, then access is allowed. If it is zero, then access is denied. Counter is counting the permits that allow access to shared resource. Thus to access the resource, a thread must be granted a permit from the semaphore.
CountDownlatch make a thread to wait until one or more events have occured. A countDownLatch is initially created with a count of the number of events that much occur before the latch is released. Each time an event happens, the count is decremented.
简短的回答:
代码没有很好地描述其哲学。
CountdownLatch 原理
用于等待直到已知数量的资源被释放。
示例:我即将开始 10 项工作,我想等到所有工作都完成。 与轮询和检查 10 项是否全部完成相反。
信号量原理
用于获取资源,直到资源耗尽,然后等待资源可用。
示例:我有一定数量的作业排队,并且我愿意分配最多 10 个线程来处理该队列。 当所有 10 个线程都忙时,下一个作业必须等待,直到有一个线程可用。 与轮询和检查线程是否可用于该作业相反。
Short Answer:
Code does not well describe the philosophy.
CountdownLatch Philosophy
Used to wait until an known-number of resources are released.
Example: I am about to kick off 10 jobs and I want to wait until all of them have finished. As opposed to polling and checking if all 10 are complete.
Semaphore Philosophy
Used to acquire resources until they run out then wait until one is available.
Example: I have some number of jobs queued and I am willing to allocate up to 10 threads to process the queue. When all 10 threads are busy the next job must wait until one becomes available. As opposed to polling and checking if a thread is available for the job.
CountDownLatch
经常用于与您的示例完全相反的情况。 通常,您会在await()
上阻塞许多线程,当倒计时达到零时,这些线程将同时启动。您还可以将其用作 MPI 样式的“屏障”,使所有线程在继续之前等待其他线程赶上某个点。
总而言之,
CountDownLatch
可以按照您在示例中所示的方式安全地使用。CountDownLatch
is frequently used for the exact opposite of your example. Generally, you would have many threads blocking onawait()
that would all start simultaneously when the countown reached zero.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.
That all said, the
CountDownLatch
can safely be used in the manner you've shown in your example.