返回
多线程入门宝典:揭秘三个线程交替打印ABC 100次的奥秘
后端
2022-12-26 06:37:05
征服并发编程:利用 Condition 变量巧妙解决经典面试题
在现代计算机世界中,并发编程已成为提升系统性能和响应速度的关键。然而,它也带来了诸多挑战,其中如何协调多个线程的执行尤为棘手。本文将深入探讨一个经典的面试题,并使用 Condition 变量揭示其巧妙的解决方案。
经典面试题:三个线程交替打印 ABC
假设有三个线程,要求它们按照 A、B、C 的顺序交替打印,每个字母打印 100 次。乍看之下,这似乎是一个简单的任务,但深入分析后你会发现,避免资源竞争和死锁是至关重要的。
Condition 变量:线程通信的利器
Java 并发库为我们提供了 Condition 变量,它可以实现线程间的通信和协调。Condition 变量包含两个关键方法:await() 和 signalAll()。当一个线程调用 await() 方法时,它会进入等待状态,直到被其他线程调用 signalAll() 方法唤醒。signalAll() 方法会唤醒所有正在等待该 Condition 变量的线程。
解决方案:Condition 变量的妙用
利用 Condition 变量,我们可以巧妙地解决三个线程交替打印 ABC 的问题。以下是具体步骤:
- 创建三个线程: 分别命名为 A、B 和 C。
- 创建 Condition 变量: 用于协调三个线程的执行。
- 线程 A 开始执行: 打印字母 A 100 次。
- 线程 A 执行完毕: 调用 signalAll() 方法唤醒其他两个线程。
- 线程 B 和 C 被唤醒: 分别打印字母 B 和 C 100 次。
- 线程 B 和 C 执行完毕: 再次调用 signalAll() 方法唤醒线程 A。
- 重复步骤 3-6: 直到三个线程都打印了 ABC 100 次。
代码示例:
以下是用 Java 实现的示例代码:
import java.util.concurrent.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class PrintABC {
private static Lock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
private static int count = 0;
public static void main(String[] args) {
// 创建三个线程
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
while (count < 100) {
lock.lock();
try {
while (count % 3 != 0) {
condition.await();
}
System.out.print("A");
count++;
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
});
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
while (count < 100) {
lock.lock();
try {
while (count % 3 != 1) {
condition.await();
}
System.out.print("B");
count++;
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
});
Thread threadC = new Thread(new Runnable() {
@Override
public void run() {
while (count < 100) {
lock.lock();
try {
while (count % 3 != 2) {
condition.await();
}
System.out.print("C");
count++;
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
});
// 启动三个线程
threadA.start();
threadB.start();
threadC.start();
}
}
总结:
利用 Condition 变量,我们成功地解决了三个线程交替打印 ABC 的问题,避免了资源竞争和死锁。理解线程通信机制对于解决并发编程中的挑战至关重要。
常见问题解答:
- Condition 变量和 wait()、notify() 方法有什么区别?
Condition 变量是 Java 并发库中专门用于线程通信的类,而 wait() 和 notify() 方法是 Java 语言中的原生方法,需要使用同步块或同步方法。 - 在多线程环境中使用 Condition 变量时需要注意什么?
使用 Condition 变量时,需要谨慎处理锁的获取和释放,以避免死锁或数据不一致。 - Condition 变量可以用于哪些类型的并发编程问题?
Condition 变量可以用于各种并发编程问题,例如生产者-消费者问题、读写锁和屏障。 - 如何避免使用 Condition 变量时出现死锁?
确保在使用 Condition 变量时始终正确获取和释放锁,并避免无限等待。 - Condition 变量和 Semaphore 变量有什么联系?
Semaphore 变量是一种特殊的 Condition 变量,它用于控制线程访问资源的数量。