0

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

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

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

4

3 回答 3

6

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

从这个意义上说,将 Semaphore 用作 CountDownLatch 有点像花园小径句;虽然在技术上是正确的,但它会导致人们误入歧途并使他们感到困惑。

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

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

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

于 2016-09-02T07:02:44.223 回答
5

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

n 个块的CountDownLatch直到达到 0。然后几乎在同一时间继续进行。

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

于 2016-09-02T07:02:14.407 回答
1

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

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

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

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

查看此 SE 问题以了解更多详细信息:

CountDownLatch 与信号量

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

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

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

CountDownLatch 的 Javadocs 引用:

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

于 2016-09-02T07:08:21.567 回答