2012-02-08 41 views
10

在java中,具我所知,volatile变量让一个线程读取/写入直接到主CPU(而不是在每个线程的高速缓存),所以使其变有形项目给其他线程。挥发性:为什么防止编译器重新排序的代码

我不知道的事情是:那么,为什么这项工作(挥发性)可以防止代码编译/ CPU重新排序声明。

谢谢:)

+0

注意这件事挥发性决策读取缓存避免是一个纯粹的理论建构,并不真的有所有的东西做什么'volatile'其实在真实硬件一样。我们只是想象一下实现可能会做的各种事情,而'volatile'保证优化不会产生我们需要在特定情况下禁止的特定行为。 – 2016-09-26 10:42:39

回答

16

这里是说明重新排序的禁令旨在解决这一问题(从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设置为truex保证是42。在Java-5之前,编译器可以自由地将写入重新排序到xv,所以你可以在之后看到x为零你已经看到v设置为true。这令人困惑,并导致微妙的错误。 Java-5存储器模型通过使易失性写入几乎等同于同步来解决此问题。

+1

我没有看到读者如何保证在42看到x。确实x = 42可以在v = true之前发生,但是reader()仍然可以看到缓存值为0,否? – Shawn 2012-02-08 04:13:08

+1

@Shawn直到正确的Java-5,但Java-5内存模型确保所有写入在易失性写入之前完成。详情请参阅链接。 – dasblinkenlight 2012-02-08 04:16:22

+0

谢谢,很高兴知道! – Shawn 2012-02-08 04:22:39

5

这就是语言仅仅是如何定义的。通俗地说,标志着Java中的一个变量volatile明确告诉它不应该重新排序报表周围或优化其价值,因为该值可能会在另一个线程同时修改了编译器。然后,JVM的特定实现负责尊重此修改器,并采取适当的预防措施,以避免错误地优化程序。

如果您想了解有关语言级别保证的更多具体细节以确保volatile正常工作,您可能需要查看the Java Language Specification's description of the Java memory model,该代码定义了控制线程行为的抽象规则。它还描述了volatile如何与这些规则进行交互。

希望这会有所帮助!

相关问题