【问题标题】:What's the point of CountDownLatch in java? [duplicate]java中CountDownLatch的意义何在? [复制]
【发布时间】:2016-09-02 06:56:53
【问题描述】:

java中的CountDownLatch是一个高级同步实用程序,用于防止特定线程开始处理,直到所有线程都准备好。

但是,Semaphore 完全可以做同样的事情。那么,CountDownLatch 的优点是什么?

还有一个问题:如果CountDownLatch 确实有一些优点,为什么它被设计为只使用一次?我认为添加 set 方法来重置计数很容易。

【问题讨论】:

  • 即使我将这个问题标记为重复但由于第二次查询,我没有这样做> 为什么它被设计为只使用一次?我认为添加 set 方法来重置计数很容易。

标签: java multithreading concurrency semaphore countdownlatch


【解决方案1】:

在语义上,它们是不同的;这很重要,因为它使您的代码更易于阅读。当我看到信号量时,我立即开始思考“有限数量的共享资源”。当我看到一个 CountDownLatch 时,我立即开始思考“一堆线程在等待'开始!'信号。”如果你在实际需要后者的代码中给我前者,那就令人困惑了。

从这个意义上说,用作 CountDownLatch 的 Semaphore 有点像garden-path sentence;虽然在技术上是正确的,但它会让人误入歧途并迷惑他们。

就更实用的用途而言,如果您只需要 CountDownLatch,它会更简单。越简单越好!

至于重用 CountDownLatch,这会使它的使用复杂化。例如,假设您正在尝试将线程 A、B 和 C 排队以完成某些工作。您让它们在闩锁上等待,然后释放它。然后你重置它,大概是为了让线程 D、E 和 F 排队进行其他工作。但是如果(由于竞争条件)线程 B 还没有真正从第一个锁存器中释放,会发生什么?如果它甚至还没有接到await() 电话怎么办?你是否关上了它的门,并告诉它与 D、E 和 F 一起等待第二次打开?如果第二次打开取决于 B 应该做的工作,那甚至可能导致死锁!

当我第一次阅读有关 CountDownLatch 的信息时,我对重置有同样的疑问。但在实践中,我什至很少想要重置一个。 “wait then go”(A-B-C,然后是 D-E-F)的每个单元自然适合创建自己的 CountDownLatch 以配合它,并且事情保持简单。

【讨论】:

  • 谢谢,为什么它被设计为只能使用一次?
  • @expoter 因为还有其他类允许重用。阅读javadoc这是一次性现象——计数无法重置。如果您需要重置计数的版本,请考虑使用CyclicBarrier
【解决方案2】:

当达到 0 时,具有 n 个块的 信号量

A CountDownLatch n 个块直到 0。然后几乎在同一时间继续。

因此,信号量就像迪斯科舞厅的看门人,倒计时闩锁就像游戏场的开场球。

【讨论】:

  • @expoter 如果你创建了一个有 N 个permitsSemaphore,你可以acquire() N 次,调用号码N+1 到acquire() 会阻塞,即它只会阻塞许可计数达到零。 --- 如果你创建一个计数为 N 的 CountDownLatch,任何对 await() 的调用都会阻塞直到计数达到零,即 N 次调用 countDown()。 --- 完全不同的功能。
  • +1 (我同意@Andreas),但作为一个小提示:semaphore.acquire(0) 仍然会阻塞,直到至少有 0 个许可,并且允许信号量具有负数允许,因此实际上将信号量用作基本上是“CountUpLatch”(从 -numberOfCounts 计数到 0)相当容易。
  • @Andreas 确实;我的表述是否太不清楚?还是您要重新制定更清晰、更详细的技术细节?
  • @JoopEggen OP 评论说他不明白,所以我澄清了。该评论现已消失。
  • @yshavit 一个 Semaphore 确实是一种反物质 CountDownLatch,不幸的是,不仅允许负数必须是可能的,而且获取需要增加,或者释放需要阻塞。但是对这些概念有一个看法是件好事。
【解决方案3】:

信号量完全可以做同样的事情。那么,CountDownLatch 的意义何在?

Semaphore 维护一组许可。如有必要,每个acquire() 都会阻塞,直到获得许可,然后再接受它。每个release() 添加一个许可,可能会释放一个阻塞的收购方。

但是,没有使用实际的许可对象; 信号量只是对可用数量进行计数并采取相应措施

Semaphore 正在阻塞进入临界区的入口,CountDownLatch 正在阻塞主线程的执行,除非其他线程完成它们的任务

查看这个 SE 问题了解更多详情:

CountDownLatch vs. Semaphore

如果 CountDownLatch 确实有一些点,为什么它被设计为只使用一次?

如果要重复使用,请使用CyclicBarrier

一种同步辅助工具,它允许一组线程相互等待以达到一个共同的障碍点。 CyclicBarriers 在涉及固定大小的线程组的程序中很有用,这些线程组必须偶尔相互等待。屏障被称为循环的,因为它可以在等待线程释放后重新使用。

CountDownLatch 的 Javadocs 引用:

CountDownLatch 是一次性现象——计数无法重置。 如果您需要重置计数的版本,请考虑使用 CyclicBarrier。

【讨论】:

    猜你喜欢
    • 2015-02-04
    • 1970-01-01
    • 2014-01-09
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    • 2010-11-30
    相关资源
    最近更新 更多