考虑下面的Java示例。请注意,两个类成员变量都没有声明为volatile
。如果我正在理解内存模型并且“之前发生”规则正确,Java实现可以优化run()
方法,以便它永远运行,即使另一个线程调用stopNow()
方法。这可能发生,因为run()
方法中没有任何内容强制线程多次读取stop
的值。那是对的吗?如果没有,为什么不呢?
class Example implements Runnable {
boolean stop = false;
int value = 0;
public void stopNow() {
stop = true;
}
public int getValue() {
return value;
}
@Override
public void run() {
// Loop until stop is set to true.
while (!stop) {
++value;
}
return;
}
}
答案 0 :(得分:4)
可以被另一个线程修改,但这不是gurranteed。这也不是线程安全的。要使变量gurranteed从另一个线程中看到,您需要执行以下任何操作
保证一个线程对字段所做的更改是可见的 其他线程仅在以下条件下:
- 写入线程释放同步锁,读取线程随后获取相同的同步锁。
- 如果某个字段被声明为volatile,则写入该字段的任何值都会被写入器之前的写入器线程刷新并使其可见 线程执行任何进一步的存储器操作(即,用于目的
在手边它立即被冲洗)。读者线程必须重新加载 每次访问时的volatile字段值。- 线程第一次访问对象的字段时,它会看到字段的初始值或自写入的值以来 其他一些帖子。
- 当一个线程终止时,所有写入的变量都被刷新到主存储器。例如,如果一个线程在终止时同步 另一个线程使用Thread.join,然后保证看到
该线程产生的影响(见§4.3.2)。
答案 1 :(得分:2)
这是对的。这是您可能想要使用volatile
的原因之一。