reentrantlock 配合 condition 实现多线程交替打印的核心是“精确唤醒 + 状态控制”:用共享状态变量(如turn)配合volatile或锁保护,为每个线程分配独立condition,循环中while+await防虚假唤醒,并注意计数边界与signalall清理。

用 ReentrantLock 配合 Condition 实现多线程交替打印,核心在于“精确唤醒 + 状态控制”,避免轮询和虚假唤醒,比 synchronized + wait/notify 更灵活可控。
明确角色与状态变量
两个线程(比如 PrintA 和 PrintB)需共享一个可变状态来决定谁该执行。不能靠线程名或顺序猜测,必须用显式变量(如 turn = 0 表示 A 打印,turn = 1 表示 B 打印)。这个变量必须被 volatile 修饰或由锁完全保护——推荐后者,即所有读写都在锁内进行,确保可见性与原子性。
为每个线程分配独立 Condition
不要共用一个 Condition,否则 signal() 可能唤醒错误线程。正确做法是:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 创建一个
ReentrantLock lock = new ReentrantLock();
- 定义两个
Condition:<code>conditionA = lock.newCondition();(供 A 等待)、conditionB = lock.newCondition();(供 B 等待) - A 执行完后调用
conditionB.signal()唤醒 B;B 执行完后调用conditionA.signal()唤醒 A
循环中使用 while + await 避免虚假唤醒
await() 必须放在 while 循环里判断条件,而不是 if。因为线程可能被意外唤醒(如信号干扰、JVM 调度),此时状态未必满足预期。例如:
lock.lock();
try {
while (turn != 0) { // 不满足就继续等
conditionA.await();
}
System.out.print("A");
turn = 1;
conditionB.signal(); // 精准唤醒 B
} finally {
lock.unlock();
}
同理,B 线程检查 turn == 1,唤醒 conditionA。
注意边界与优雅退出
如果只打印固定次数(如 1~10),需在循环中加计数器,并在每次打印后检查是否结束。一旦完成,应确保不继续 signal() 或 await(),避免唤醒已终止线程导致异常。更稳妥的做法是:所有线程完成任务后,主动调用 conditionA.signalAll() 和 conditionB.signalAll() 清理等待队列(尤其在异常退出时),防止 JVM 挂起。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










