synchronized实现多线程交替输出需共用锁对象和状态变量,线程在同步块内用while循环检查条件、wait()等待、notify()唤醒,避免虚假唤醒与死锁,推荐私有final锁对象而非synchronized方法。

用 synchronized 实现多线程交替输出,核心是让两个(或多个)线程共用一把锁、一个状态标识,并通过 wait() 和 notify() 协作控制执行顺序。关键不在“加锁”本身,而在“谁该运行、谁该等待”的判断逻辑。
共享锁对象 + 状态变量控制轮次
必须有一个所有线程都能访问的共享对象作为锁(比如 Object lock = new Object()),再配一个 volatile 或受锁保护的状态变量(如 int turn = 0 或 String current = "A")。每个线程进入同步块后先检查是否轮到自己:不是就 wait();是就执行任务,更新状态,再 notify() 唤醒另一个线程。
- 状态变量不能只靠局部判断,必须在
synchronized块内读写,否则存在竞态 -
wait()必须在循环中调用(即while (!condition) wait()),防止虚假唤醒 -
notify()只唤醒一个等待线程,对两个线程场景够用;若线程数 >2,建议用notifyAll()
典型错误:漏掉 final notify 或未处理循环结束
常见陷阱是 for 循环结束后没调用 notify()。例如字母线程打印完 Z 后直接退出,数字线程还在 wait(),导致程序无法正常终止。解决方法是在循环外补一次 notify(),确保对方线程能被唤醒并检查退出条件。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 不要依赖“输出看起来正确”来判断逻辑完整——要观察线程是否全部自然结束
- 如果使用
notifyAll(),需配合更严谨的 while 条件判断,避免唤醒错的线程后立即又 wait
适用于两个线程的简洁模板
以下结构可复用于 A1B2、奇偶数、ABAB 等场景:
- 定义共享锁
Object lock = new Object()和轮次标识int state = 0 - 线程 A:进入同步块 →
while (state != 0) wait()→ 打印/处理 →state = 1→notify() - 线程 B:进入同步块 →
while (state != 1) wait()→ 打印/处理 →state = 0→notify() - 注意:两个线程的 while 条件必须互斥且覆盖全部可能值
不推荐直接 synchronized 方法,而要用同步块
虽然给整个方法加 synchronized 也能实现,但粒度太粗——它锁的是当前实例(this)或类对象,容易引发不必要的阻塞,也不利于扩展(比如后续想加第三个线程)。明确使用同步块锁定同一个对象,语义清晰、可控性强,也方便调试和复用。
- 避免锁
this,尤其当对象被外部持有时,可能造成意外死锁 - 锁对象应是私有、final、不对外暴露的,比如
private final Object lock = new Object()
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










