CyclicBarrier 和 CountDownLatch

2023-08-14 16:23:16 浏览数 (2)

引言

在多线程编程中,我们经常会遇到一些需要线程间协同工作的场景。CyclicBarrierCountDownLatch 就是两种常用的同步工具,它们能够帮助我们实现线程间的协调和同步。本文将深入探讨这两种同步工具的实现原理,并附上代码演示。

CyclicBarrier 的实现原理

CyclicBarrier 可以用来等待一组线程到达一个共同的栅栏点,然后同时开始执行下一步任务。它的内部实现主要依靠一个计数器和一个等待队列。

当我们创建一个 CyclicBarrier 实例时,我们需要传入一个整数值,表示需要等待的线程数量。当每个线程调用 await() 方法时,计数器会递减,然后线程会进入等待状态。当计数器达到零时,所有等待的线程都会被释放,可以继续执行下一步任务,同时计数器会被重置,可以被下一轮使用。

以下是一个简化的 CyclicBarrier 实现的示例代码:

代码语言:java复制
public class CyclicBarrier {
    private int parties;
    private int count;

    public CyclicBarrier(int parties) {
        this.parties = parties;
        this.count = parties;
    }

    public synchronized void await() throws InterruptedException {
        count--;

        if (count > 0) {
            this.wait();
        } else {
            count = parties;
            this.notifyAll();
        }
    }
}

CountDownLatch 的实现原理

CountDownLatch 是另一种线程同步工具,它允许一个或多个线程等待其他线程完成操作后再继续执行。其实现原理较为简单,主要依赖于一个计数器和线程等待机制。

在创建 CountDownLatch 实例时,需要传入一个整数值,表示需要等待的操作数。每个操作完成后,调用 countDown() 方法,计数器会递减。等待的线程可以通过调用 await() 方法来阻塞,直到计数器减到零。

以下是一个简单的 CountDownLatch 实现的示例代码:

代码语言:java复制
public class CountDownLatch {
    private int count;

    public CountDownLatch(int count) {
        this.count = count;
    }

    public synchronized void countDown() {
        count--;

        if (count == 0) {
            this.notifyAll();
        }
    }

    public synchronized void await() throws InterruptedException {
        while (count > 0) {
            this.wait();
        }
    }
}

代码演示

现在让我们通过一个示例场景来演示如何使用 CyclicBarrierCountDownLatch

假设我们有一个多线程任务,需要等待所有线程都完成后再继续进行。首先,我们可以使用 CountDownLatch 来实现这个需求:

代码语言:java复制
public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        int threadCount = 3;
        CountDownLatch latch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i  ) {
            Thread thread = new Thread(() -> {
                // 模拟线程执行
                System.out.println("Thread "   Thread.currentThread().getId()   " is working.");
                latch.countDown();
            });
            thread.start();
        }

        latch.await();
        System.out.println("All threads have finished.");
    }
}

接下来,我们使用 CyclicBarrier 来实现一个多线程任务的同步:

代码语言:java复制
public class CyclicBarrierDemo {
    public static void main(String[] args) throws InterruptedException {
        int threadCount = 3;
        CyclicBarrier barrier = new CyclicBarrier(threadCount);

        for (int i = 0; i < threadCount; i  ) {
            Thread thread = new Thread(() -> {
                // 模拟线程执行
                System.out.println("Thread "   Thread.currentThread().getId()   " is working.");
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread "   Thread.currentThread().getId()   " continues.");
            });
            thread.start();
        }
    }
}

结论

CyclicBarrierCountDownLatch 都是用于线程同步的重要工具,分别适用于不同的场景。CyclicBarrier 可以用于多个线程等待彼此达到一个栅栏点,然后同时继续执行,而 CountDownLatch 则用于一个或多个线程等待其他线程完成后再继续执行。了解它们的实现原理和使用方法,将有助于我们在多线程编程中更好地处理并发场景。

0 人点赞