CountDownLatch 与信号量

发布于 2024-07-06 04:49:08 字数 1262 浏览 9 评论 0 原文

使用

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();

除了第二种情况,锁存器不能重用,更重要的是你需要提前知道将创建多少个线程(或者等到它们全部启动后再使用)创建闩锁。)

那么在什么情况下闩锁可能更可取呢?

Is there any advantage of using

java.util.concurrent.CountdownLatch

instead of

java.util.concurrent.Semaphore?

As far as I can tell the following fragments are almost equivalent:

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();

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.)

So in what situation might the latch be preferable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

二货你真萌 2024-07-13 04:49:08

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() and 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.

心安伴我暖 2024-07-13 04:49:08

简短摘要:

  1. 信号量CountDownLatch 有不同的用途。

  2. 使用Semaphore来控制线程对资源的访问。

  3. 使用CountDownLatch等待所有线程完成

信号量 来自 docs.oracle.com :

信号量维护一组许可。 如果有必要,每个 acquire() 都会阻塞,直到许可可用,然后获取它。 每个release()都会添加一个许可,可能会释放一个阻塞的获取者。 然而,没有使用实际的许可对象; Semaphore 只是保留可用数量的计数并相应地执行操作。

它是如何工作的?

信号量用于控制访问文件、网络套接字等资源的并发线程数。

信号量使用计数器值进行初始化,该计数器值提供允许的最大许可。

acquire() 将减少许可数量。 release() 将增加许可证数量。 在任何时候,都不可能有更多的资源所有者超过允许的许可证数量。

当您的资源数量有限时(可能是线程数、网络套接字数、网络打印机数等),它很有用。

Javadocs 中的 CountDownLatch 定义:

一种同步辅助工具,允许一个或多个线程等待,直到其他线程中执行的一组操作完成。

它是如何工作的?

CountDownLatch 通过设置一个用线程数初始化的计数器来工作。 当线程完成其执行时,计数器就会递减。 当所有线程完成执行后,计数器将归零。

CountDownLatch 使用案例:通过 howtodoinjava.com 作者:Lokesh Gupta

  1. 最大并行度
  2. 等待所有线程完成后再开始执行其他任务
  3. 死锁检测

Short summary:

  1. Semaphore and CountDownLatch serves different purpose.

  2. Use Semaphore to control thread access to resource.

  3. Use CountDownLatch to wait for completion of all threads

Semaphore definition of Semaphore from docs.oracle.com :

A Semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it. Each release() adds a permit, potentially releasing a blocking acquirer. However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly.

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:

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?

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

  1. Maximum Parallelism
  2. Wait for all threads to complete before start of executing other task
  3. Deadlock detection
甜宝宝 2024-07-13 04:49:08

假设您走进高尔夫专卖店,希望找到一个四人组,

当您排队等待一位专卖店服务员的开球时间时,实际上您调用了 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 called proshopVendorSemaphore.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 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)

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.

不喜欢何必死缠烂打 2024-07-13 04:49:08

查看免费提供的源代码,这两个类的实现没有什么神奇之处,因此它们的性能应该大致相同。 选择能让您的意图更加明显的一项。

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.

ゃ懵逼小萝莉 2024-07-13 04:49:08

CountdownLatch 使线程等待 await() 方法,直到计数达到零。 因此,也许您希望所有线程都等待 3 次调用某项,然后所有线程都可以运行。 Latch 通常无法重置。

信号量允许线程检索许可,这可以防止同时执行太多线程,如果无法获得继续所需的许可,则会阻塞。 许可可以返回到信号量,允许其他等待线程继续进行。

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.

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.

﹎☆浅夏丿初晴 2024-07-13 04:49:08

信号量通过使用计数器来控制对共享资源的访问。 如果计数器大于零,则允许访问。 如果为零,则访问被拒绝。 计数器正在计算允许访问共享资源的许可。 因此,要访问资源,线程必须获得信号量的许可。

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.

耳钉梦 2024-07-13 04:49:08

简短的回答:

代码没有很好地描述其哲学。

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.

浅语花开 2024-07-13 04:49:08

CountDownLatch 经常用于与您的示例完全相反的情况。 通常,您会在 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!

您还可以将其用作 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();
}

总而言之,CountDownLatch 可以按照您在示例中所示的方式安全地使用。

CountDownLatch 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.

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.

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 CountDownLatch can safely be used in the manner you've shown in your example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文