Java Volatile:为什么要阻止编译器重新排序代码
据我所知,在java中,volatile变量使线程直接读/写主CPU(不在每个线程的缓存中),因此使其更改对其他线程可见 我不知道的是:那么,为什么这项工作(volatile)可以阻止编译器/CPU对代码语句进行重新排序呢Java Volatile:为什么要阻止编译器重新排序代码,java,multithreading,volatile,Java,Multithreading,Volatile,据我所知,在java中,volatile变量使线程直接读/写主CPU(不在每个线程的缓存中),因此使其更改对其他线程可见 我不知道的是:那么,为什么这项工作(volatile)可以阻止编译器/CPU对代码语句进行重新排序呢 谢谢:)这就是语言的定义。非正式地说,在Java中标记一个变量volatile,特别告诉编译器不应该对其周围的语句重新排序或对其值进行优化,因为该值可能会在另一个线程中同时修改。JVM的特定实现负责遵守此volatile修饰符,并采取适当的预防措施以避免错误地优化程序 如果您
谢谢:)这就是语言的定义。非正式地说,在Java中标记一个变量
volatile
,特别告诉编译器不应该对其周围的语句重新排序或对其值进行优化,因为该值可能会在另一个线程中同时修改。JVM的特定实现负责遵守此volatile
修饰符,并采取适当的预防措施以避免错误地优化程序
如果您想了解有关哪些语言级别的保证可以确保volatile
正常工作的更具体的细节,您可能需要查看,它定义了控制线程行为的抽象规则。它还描述了volatile
如何与这些规则交互
希望这有帮助 这是一个很好的例子,说明了禁止再订购旨在解决的问题(摘自):
在本例中,
v
是易变的,但x
不是。如果写入程序和读取器同时执行,并且读取器看到v
设置为true
,x
保证为42
。在Java-5之前,编译器可以自由地对x
和v
的写入进行重新排序,因此在看到v
设置为true
后,您可以看到x
为零。这令人困惑,并导致微妙的错误。Java-5内存模型通过使易失性写入几乎等同于同步来解决这个问题。我不知道如何保证读卡器(见第42页的x)。确保x=42可以发生在v=true之前,但是reader()仍然可以看到缓存值0,否?@Shawn,直到Java-5这是正确的,但是Java-5内存模型确保所有写入都在易失性写入之前完成。有关详细信息,请参阅链接。我只是根据这个答案运行了我的代码,并注意到以下事实。如果v声明为true,编译器可以删除行v=true
,并且x的值在reader()中保持为0。请参阅,但如果在writer()中设置v之后设置了x,则reader()会将x设置为42或0注意,关于volatile使读取避免缓存的这件事纯粹是一个理论构造,实际上与真正的硬件上的volatile
实际功能没有太大关系。我们只是想象一个实现可能会做各种事情,volatile
保证优化不会产生我们需要在特定情况下禁止的特定行为。
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.
}
}
}