java CountDownLatch与信号量

uhry853o  于 2023-04-04  发布在  Java
关注(0)|答案(7)|浏览(155)

使用有什么好处吗
java.util.concurrent.CountdownLatch
而不是
是吗?
据我所知,以下片段几乎是等效的:

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

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

除了在第2种情况下,锁存器不能被重用,更重要的是,你需要提前知道有多少线程将被创建(或者等到它们都被启动后再创建锁存器)。
那么,在什么情况下,闩锁可能更可取呢?

anhgbhbe

anhgbhbe1#

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可以安全地以示例中所示的方式使用。

8cdiaqws

8cdiaqws2#

CountDownLatch用于启动一系列线程,然后等待所有线程完成(或者直到它们调用countDown()给定次数)。
信号量用于控制使用资源的并发线程的数量。该资源可以是类似于文件的东西,也可以是通过限制执行线程数量的cpu。信号量的计数可以随着不同线程调用acquire()release()而增加和减少。
在您的示例中,您实际上是将信号量用作一种CountUPLatch。考虑到您的意图是等待所有线程完成,使用CountdownLatch可以使您的意图更清晰。

8fq7wneg

8fq7wneg3#

  • 简短摘要:*
  1. SemaphoreCountDownLatch有不同的用途。
    1.使用Semaphore控制线程对资源的访问。
    1.使用CountDownLatch等待所有线程完成
    Javadocs中的Semaphore定义:
    Semaphore维护一组许可证。每个acquire()在必要时阻塞,直到有一个 permit 可用,然后获取它。每个release()添加一个许可证,可能会释放一个阻塞的收单方。
    但是,没有使用实际的许可对象;Semaphore仅保持可用数量的计数并相应地动作。
  • 它是如何运作的 *

信号量用于控制使用资源的并发线程的数量。
当不同的线程调用acquire()release()时,Semaphore上的计数可以上下浮动。但是在任何时候,线程数都不能超过信号量计数。

  • Semaphore使用案例:*

1.任务数量,占用大量CPU/内存
1.线程池中的线程数

  1. JDBC连接池中的连接数
    1.网络中的连接数
    Javadocs中的CountDownLatch定义:
    一种同步辅助工具,允许一个或多个线程等待,直到其他线程中正在执行的一组操作完成。
  • 它是如何运作的 *

CountDownLatch的工作原理是有一个计数器初始化线程数,每次线程完成执行时计数器就递减。当计数器达到零时,意味着所有线程都完成了执行

  • CountDownLatch使用案例:*

1.最大并行度
1.在开始执行其他任务之前,等待所有线程完成
1.死锁检测

p1tboqfb

p1tboqfb4#

假设你走进高尔夫专卖店,想找个四人组,
当你排队从一个专业商店服务员那里得到开球时间时,本质上你叫proshopVendorSemaphore.acquire(),一旦你得到开球时间,你叫proshopVendorSemaphore.release()。任何免费的服务员都可以为您服务,即共享资源。
现在你走到起动器,他启动CountDownLatch(4)并调用await()等待其他人,对于你的一部分,你称为签到,即CountDownLatchcountDown(),其余的四人也是如此。当所有到达时,起动器给出继续(await()调用返回)
现在,在九洞之后,当你们每个人休息时,假设让先发球员再次上场,他使用“新”CountDownLatch(4)开球10洞,与1洞相同的等待/同步。
然而,如果启动器使用CyclicBarrier开始,他可以在孔10中重置相同的示例,而不是使用& throw的第二个闩锁。

jv2fixgn

jv2fixgn5#

查看免费提供的源代码,这两个类的实现并没有什么魔力,所以它们的性能应该差不多。选择一个使您的意图更明显的类。

5lwkijsr

5lwkijsr6#

CountdownLatch使线程等待await()方法,直到计数达到零。所以也许你想让所有线程等待,直到3次调用某个东西,然后所有线程都可以去。Latch通常不能重置。
Semaphore允许线程检索许可证,这可以防止太多线程同时执行,如果它无法获得继续执行所需的许可证,则会阻塞。许可证可以返回给Semaphore,以允许其他等待的线程继续执行。

00jrzges

00jrzges7#

信号量通过使用计数器来控制对共享资源的访问。如果计数器大于零,则允许访问。如果计数器为零,则拒绝访问。计数器正在计算允许访问共享资源的许可。因此,要访问资源,线程必须从信号量获得许可。
CountDownlatch使线程等待,直到发生一个或多个事件。countDownLatch最初创建时,会对闩锁释放前发生的事件数进行计数。每次事件发生时,计数都会递减。

相关问题