while循环和线程的无限循环问题

使用一个基本的例子来说明我的问题,我有两个几乎相同的代码位。

此代码使while循环无限运行。

 private boolean loadAsset() { new Thread(new Runnable() { @Override public void run() { // Do something loaded = true; } }).start(); while (!loaded) { // System.out.println("Not Loaded"); } System.out.println("Loaded"); return false; } 

但是这个代码(即在while循环中执行某些操作)会导致已成功计算loaded变量,并允许while循环中断并完成方法。

 private boolean loadAsset() { new Thread(new Runnable() { @Override public void run() { // Do something loaded = true; } }).start(); while (!loaded) { System.out.println("Not Loaded"); } System.out.println("Loaded"); return false; } 

任何人都可以向我解释为什么会这样吗?

检查’loaded’是否明确声明为volatile。

说明:如果多个线程读取和/或写入变量,则需要采取适当的线程安全措施。 一种这样的线程安全措施是易失性的,它适用于原始值(或对象引用 ),它们被读取或写为“简单”动作,其值在给定的情况下写入而不依赖于先前读取的值。 有关更多信息,我在我的网站上有一篇关于volatile的文章(以及一般的线程安全的其他信息)可能会有所帮助。

第一个循环仅“出现”无限运行。 您实际上正在运行“活动等待”,烧掉100%的CPU,这样您的操作系统或JVM就无法进行上下文切换并让其他线程运行。

另一方面,使用System.out.println() ,涉及I / O,导致稍微“无效等待”。 OS或JVM可以切换上下文,另一个线程启动。

如果你运行你的第一个程序10个小时,我肯定循环最终会破坏

如果loaded不是易失性的,JIT可以通过将其放入寄存器而不是每次都从内存加​​载来自由优化它。 在第二种情况下,循环过于复杂,JIT无法假设每次都不需要loaded

注意:它是JIT而不是优化代码的javac编译器。

阅读内存一致性错误 。 基本上,不同的线程对于应该是相同数据的内容具有不一致的视图。 要解决此问题,请阅读同步 。 或者简单地声明loadedvolatile ,因为它的值仅由单个线程写入。

我相信你正在经历一个空荡荡的等待 ,它永远不会睡觉。 因此,您设置加载到true的线程永远不会运行。