java - Android ART 和 HotSpot 在非易失性变量可见性方面的行为是否不同?
问题描述
我在 HotSpot 和 Android ART 上测试了以下代码,但结果不同。
在 HotSpot 上,MyThread
永远不会得到更新isRunning
,它isRunning
总是得到 = true ......但是当我在 ART 上测试它时,MyThread
可以正常获取更新isRunning
并退出循环......
据我所知,java 发生前规则,非易失性在多线程中不可见,就像下面代码在 Hotspot 上的行为一样。
它是否取决于VM实现?或者也许 Android ART 有自己的优化?
class MyThread extends Thread {
public boolean isRunning = true;
@Override
public void run() {
System.out.println("MyThread running");
while (true) {
if (isRunning == false) break;
}
System.out.println("MyThread exit");
}
}
public class RunThread{
public static void main(String[] args) {
new RunThread().runMain();
}
public void runMain() {
MyThread thread = new MyThread();
try {
thread.start();
Thread.sleep(500);
thread.isRunning = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
解决方案
非易失性在多线程中不可见,就像下面代码在 Hotspot 上的行为一样。
这不太对。非易失性写入,没有任何额外的同步或其他发生前的关系,不能保证对另一个线程中相同变量的读取可见。不过,它是允许可见的。尽管没有发生之前的关系,但我绝对看到 HotSpot 使跨线程的写入可见。根据我在这方面的经验,我怀疑如果您Thread.sleep
在代码中删除该调用,HotSpot 也会使写入对isRunning
线程可见,尽管写入和读取之间没有任何发生前的关系。
您绝对正确,它是特定于 VM 的,而且它可能/可能甚至是特定于处理器架构的,因为不同的架构可能会为“免费”提供不同数量的同步,或者具有不同数量的缓存会影响是否读取内存地址从核心的缓存或从主内存中获取。
总之,你不应该依赖这种行为在任何特定的虚拟机上以任何特定的方式工作——它可能会在没有警告的情况下发生变化。
推荐阅读
- julia - Julia 1.2 下无法安装 Genie 框架
- arrays - 如何在laravel中将数组插入多行
- python - 重置 Python/Matplotlib 中绘图的默认字体/颜色
- python - sum 每次都可以被列表的一个元素整除
- c - C - 将错误的指针类型传递给函数
- c++ - 我不能在 C++ 上使用 fmt 库头文件
- java - 更新集合内的列表 dbref
- python - 如何在 Python 中使用 BeautifulSoup 从 html 中提取特定文本?
- sql - ORA-00906: 缺少左括号 oracle 错误可能是因为我弄乱了语法
- python - 在python中实现Backwards Euler方法来解决钟摆