引言
在多线程编程中,我们经常会遇到一些需要线程间协同工作的场景。CyclicBarrier
和 CountDownLatch
就是两种常用的同步工具,它们能够帮助我们实现线程间的协调和同步。本文将深入探讨这两种同步工具的实现原理,并附上代码演示。
CyclicBarrier 的实现原理
CyclicBarrier
可以用来等待一组线程到达一个共同的栅栏点,然后同时开始执行下一步任务。它的内部实现主要依靠一个计数器和一个等待队列。
当我们创建一个 CyclicBarrier
实例时,我们需要传入一个整数值,表示需要等待的线程数量。当每个线程调用 await()
方法时,计数器会递减,然后线程会进入等待状态。当计数器达到零时,所有等待的线程都会被释放,可以继续执行下一步任务,同时计数器会被重置,可以被下一轮使用。
以下是一个简化的 CyclicBarrier
实现的示例代码:
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
实现的示例代码:
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();
}
}
}
代码演示
现在让我们通过一个示例场景来演示如何使用 CyclicBarrier
和 CountDownLatch
。
假设我们有一个多线程任务,需要等待所有线程都完成后再继续进行。首先,我们可以使用 CountDownLatch
来实现这个需求:
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
来实现一个多线程任务的同步:
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();
}
}
}
结论
CyclicBarrier
和 CountDownLatch
都是用于线程同步的重要工具,分别适用于不同的场景。CyclicBarrier
可以用于多个线程等待彼此达到一个栅栏点,然后同时继续执行,而 CountDownLatch
则用于一个或多个线程等待其他线程完成后再继续执行。了解它们的实现原理和使用方法,将有助于我们在多线程编程中更好地处理并发场景。