Java多线程同步死锁问题:计数器wait/notify实现故障求助
问题分析与解决
你的代码出现死锁的核心原因有两个:
- 用
if而非while检查等待条件:线程被notify()唤醒后不会重新判断当前条件是否满足,直接继续执行,导致不符合执行条件时仍操作变量,最终引发线程互相等待。 - 唤醒逻辑的随机性:
notify()只会随机唤醒一个等待线程,如果唤醒的是同类线程(比如增量线程唤醒另一个增量线程),该线程醒来后仍不满足执行条件,会再次进入等待,最终所有线程都陷入等待。
关键修改点
- 将等待条件的
if替换为while,确保线程被唤醒后重新检查条件,只有满足条件才继续执行。 - 调整方法内的逻辑顺序:先判断是否允许执行操作,再进行增减,避免先修改变量后判断导致的逻辑混乱。
- 用
notifyAll()替代notify(),确保所有等待线程都能收到唤醒信号,避免同类线程被唤醒后再次等待的情况。
修改后的完整代码
class Mythread implements Runnable { Counter q; int i = 1; Mythread(Counter q) { this.q = q; new Thread(this).start(); } @Override public void run() { while (i <= 10) { q.increment(); i++; } } } class Mythread2 implements Runnable { Counter q; int i = 1; Mythread2(Counter q) { this.q = q; new Thread(this).start(); } @Override public void run() { while (i <= 10) { q.decrement(); i++; } } } class Counter { private int count = 0; // 调整初始值为0,避免decrement线程一开始就等待 private static final int MAX_COUNT = 3; // 用常量定义阈值,更易维护 synchronized void increment() { try { // 当count达到最大值时,等待直到被减到0 while (count >= MAX_COUNT) { System.out.println("已达最大值" + MAX_COUNT + ",等待递减至0"); wait(); } System.out.println("递增后:" + ++count); notifyAll(); // 唤醒所有等待线程 } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复中断状态 } } synchronized void decrement() { try { // 当count小于0时,等待直到有递增操作 while (count < 0) { System.out.println("count已小于0,等待递增"); wait(); } System.out.println("递减后:" + count--); notifyAll(); // 唤醒所有等待线程 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } class q3 { public static void main(String[] args) { Counter q = new Counter(); new Mythread(q); new Mythread2(q); } }
代码说明
- while循环检查条件:每次线程被唤醒后,都会重新判断当前count是否符合执行条件,确保只有满足条件时才进行增减操作。
- 调整初始值:将count初始值设为0,避免decrement线程一开始就进入等待状态,保证程序能正常启动。
- 使用notifyAll():确保所有等待的线程都能收到唤醒信号,避免出现同类线程被唤醒后再次等待的情况,彻底解决死锁隐患。
- 恢复中断状态:捕获InterruptedException后恢复线程的中断状态,符合Java线程中断的最佳实践。
内容的提问来源于stack exchange,提问作者Viraj Desai
相关产品推荐
相关产品推荐

