易失性:为什么要阻止编译器重新排序代码

在java中,据我所知,volatile变量使线程直接读/写到主CPU(而不是每个线程的缓存中),因此将其更改显示给其他线程。

我不知道的是:那么,为什么这个工作(volatile)可以阻止编译器/ CPU重新排序代码语句。

谢谢 :)

这是一个非常好的例子,说明禁止重新排序旨在解决的问题(取自此处 ):

 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不是。 如果同时执行writer和reader并且读者将v设置为true ,则x保证为42 。 在Java-5之前,编译器可以自由地重写对xv的写入,因此在看到v set为true 之后 ,你可以看到x为零。 这令人困惑,并导致微妙的错误。 Java-5内存模型通过使易失性写入几乎等同于同步来解决此问题。

这就是语言的定义方式。 非正式地,在Java中标记变量volatile特别告诉编译器它不应该重新排序它周围的语句或优化它的值,因为该值可能在另一个线程中同时被修改。 然后,JVM的特定实现负责遵守此volatile修饰符并采取适当的预防措施,以避免错误地优化程序。

如果您想了解有关确保volatile正常工作的语言级保证的更多具体细节,您可能需要查看Java语言规范对Java内存模型的描述,该描述定义了管理线程行为的抽象规则。 它还描述了volatile如何与这些规则交互。

希望这可以帮助!