Java多线程设置stop布尔变量无法终止线程死循环问题求解
问题根源
这是Java多线程场景下的共享变量可见性问题,由Java内存模型(JMM)的设计规则导致:
- Java内存模型规定所有共享变量默认存储在主内存中,每个线程有独立的工作内存,线程对变量的所有读写操作都必须在工作内存中完成,不能直接操作主内存的变量
- 你代码中的
stop变量没有做任何同步处理,子线程运行时会一直读取自己工作内存中缓存的stop=false副本,感知不到主线程在主内存中对stop变量的修改,因此出现无限循环。 - 额外补充:你的循环属于无阻塞的纯计算热点循环,JIT即时编译器还可能做激进优化,直接把
shouldRun()的返回值替换为常量true,完全跳过变量读取逻辑,进一步加剧了无限循环问题。
修复方案
方案1:给stop变量添加volatile修饰符
volatile关键字可以同时保证共享变量的可见性,且禁止指令重排序优化:被volatile修饰的变量,修改后会立即同步回主内存,读取时会直接从主内存拉取最新值,不会使用线程工作内存的缓存。
修改后代码片段:
class ThreadWithStop implements Runnable { // 添加volatile修饰符 private volatile boolean stop; // 其余代码无需改动 }
方案2:访问stop变量时加同步锁
synchronized同步机制除了保证操作原子性,也能保证变量可见性:进入同步块时会清空工作内存中对应变量的缓存,直接从主内存读取最新值,退出同步块时会把变量修改结果强制同步回主内存。
修改示例:
// 给stop的读取方法加synchronized修饰 public synchronized boolean shouldRun() { return !this.stop; } // 给stop的修改方法也加synchronized修饰 public synchronized void stopThread() { this.stop = true; }
额外建议
生产环境更推荐使用JDK自带的线程中断机制来终止线程,比自定义标志位的鲁棒性更强,可以兼容线程处于阻塞状态的终止场景。
内容的提问来源于stack exchange,提问作者avocado
相关产品推荐
相关产品推荐

