在java中,具我所知,volatile变量让一个线程读取/写入直接到主CPU(而不是在每个线程的高速缓存),所以使其变有形项目给其他线程。挥发性:为什么防止编译器重新排序的代码
我不知道的事情是:那么,为什么这项工作(挥发性)可以防止代码编译/ CPU重新排序声明。
谢谢:)
在java中,具我所知,volatile变量让一个线程读取/写入直接到主CPU(而不是在每个线程的高速缓存),所以使其变有形项目给其他线程。挥发性:为什么防止编译器重新排序的代码
我不知道的事情是:那么,为什么这项工作(挥发性)可以防止代码编译/ CPU重新排序声明。
谢谢:)
这里是说明重新排序的禁令旨在解决这一问题(从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存储器模型通过使易失性写入几乎等同于同步来解决此问题。
我没有看到读者如何保证在42看到x。确实x = 42可以在v = true之前发生,但是reader()仍然可以看到缓存值为0,否? – Shawn 2012-02-08 04:13:08
@Shawn直到正确的Java-5,但Java-5内存模型确保所有写入在易失性写入之前完成。详情请参阅链接。 – dasblinkenlight 2012-02-08 04:16:22
谢谢,很高兴知道! – Shawn 2012-02-08 04:22:39
这就是语言仅仅是如何定义的。通俗地说,标志着Java中的一个变量volatile
明确告诉它不应该重新排序报表周围或优化其价值,因为该值可能会在另一个线程同时修改了编译器。然后,JVM的特定实现负责尊重此修改器,并采取适当的预防措施,以避免错误地优化程序。
如果您想了解有关语言级别保证的更多具体细节以确保volatile
正常工作,您可能需要查看the Java Language Specification's description of the Java memory model,该代码定义了控制线程行为的抽象规则。它还描述了volatile
如何与这些规则进行交互。
希望这会有所帮助!
注意这件事挥发性决策读取缓存避免是一个纯粹的理论建构,并不真的有所有的东西做什么'volatile'其实在真实硬件一样。我们只是想象一下实现可能会做的各种事情,而'volatile'保证优化不会产生我们需要在特定情况下禁止的特定行为。 – 2016-09-26 10:42:39