在java中,据我所知,volatile变量使一个线程直接读/写到主CPU(而不是每个线程的缓存中),因此将其更改显示给其他线程。
我不知道的是:那么,为什么这个(volatile的)工作可以阻止编译器/ CPU重新排序代码语句。
谢谢:)
答案 0 :(得分:20)
这是一个非常好的例子,说明禁止重新排序旨在解决的问题(取自here):
class VolatileExample {
int x = 0;
volatile boolean v = false;
public void writer() {
x = 42;
v = true;
}
public void reader() {
if (v == true) {
//uses x - guaranteed to see 42.
}
}
}
在此示例中,v
是易变的,但x
不是。如果同时执行作者和读者,并且读者将v
设置为true
,则x
保证为42
。在Java-5之前,编译器可以自由地将写入重新排序为x
和v
,因此您可以在之后看到x
为 看到v
设置为true
。这令人困惑,并导致微妙的错误。 Java-5内存模型通过使易失性写入几乎等同于同步来解决此问题。
答案 1 :(得分:5)
这就是语言的定义方式。非正式地,在Java中标记变量volatile
特别告诉编译器它不应该重新排序它周围的语句或优化它的值,因为该值可能在另一个线程中同时修改。然后,JVM的特定实现负责尊重此volatile
修饰符,并采取适当的预防措施,不要错误地优化程序。
如果您想了解有关确保volatile
正常工作的语言级保证的更多具体细节,您可能需要查看the Java Language Specification's description of the Java memory model,它定义了管理线程行为的抽象规则。它还描述了volatile
如何与这些规则进行互动。
希望这有帮助!