Java 中 CountDownLatch 和 CyclicBarrier 的区别是什么?

· 约 3 分钟读完 · 第 83 / 274 章

推荐答案

CountDownLatch 和 CyclicBarrier 都是 Java 并发包中用于线程同步的工具类,但它们的使用场景和机制有所不同。

  • CountDownLatch:

    • 用于一个或多个线程等待其他线程完成操作。
    • 初始化时指定一个计数值,线程通过调用 countDown() 方法减少计数值,当计数值减到 0 时,等待的线程被唤醒。
    • 计数值不可重置,一旦减到 0,就不能再次使用。
  • CyclicBarrier:

    • 用于多个线程相互等待,直到所有线程都到达某个屏障点。
    • 初始化时指定参与线程的数量,线程通过调用 await() 方法等待,当所有线程都到达屏障点时,屏障打开,所有线程继续执行。
    • 屏障可以重复使用,即所有线程到达屏障点后,屏障会自动重置,可以再次使用。

本题详细解读

CountDownLatch

CountDownLatch 是一个同步辅助类,允许一个或多个线程等待其他线程完成操作。它通过一个计数器来实现,计数器的初始值由构造函数指定。每当一个线程完成了自己的任务后,调用 countDown() 方法将计数器减 1。当计数器减到 0 时,所有等待的线程(通过 await() 方法等待的线程)将被唤醒并继续执行。

CountDownLatch 的典型使用场景是主线程等待多个子线程完成任务后再继续执行。例如,主线程启动多个子线程执行任务,然后调用 await() 方法等待所有子线程完成任务后再继续执行后续操作。

CyclicBarrier

CyclicBarrier 也是一个同步辅助类,但它允许多个线程相互等待,直到所有线程都到达某个屏障点(barrier point)。CyclicBarrier 的构造函数需要指定参与线程的数量,每个线程通过调用 await() 方法表示自己已经到达屏障点,并等待其他线程到达。

当所有线程都到达屏障点时,屏障打开,所有线程继续执行。与 CountDownLatch 不同的是,CyclicBarrier 的屏障可以重复使用,即所有线程到达屏障点后,屏障会自动重置,可以再次使用。

CyclicBarrier 的典型使用场景是多个线程需要相互等待,直到所有线程都完成某个阶段的任务后再继续执行。例如,多个线程分别计算数据的一部分,然后等待所有线程都完成计算后再进行下一步操作。

区别总结

  • 使用场景:

    • CountDownLatch 适用于一个或多个线程等待其他线程完成操作。
    • CyclicBarrier 适用于多个线程相互等待,直到所有线程都到达某个屏障点。
  • 计数器:

    • CountDownLatch 的计数器不可重置,一旦减到 0,就不能再次使用。
    • CyclicBarrier 的屏障可以重复使用,所有线程到达屏障点后,屏障会自动重置。
  • 线程行为:

    • CountDownLatch 的线程通过 countDown() 方法减少计数器,通过 await() 方法等待计数器减到 0。
    • CyclicBarrier 的线程通过 await() 方法等待其他线程到达屏障点。