2010-04-22 84 views
8

在Java中将变量标记为volatile可确保每个线程都能看到最后写入的值,而不是一些陈旧的值。我想知道这是如何实现的。 JVM是否会发出特殊指令来刷新CPU兑换次数?volatile如何实际工作?

+0

相关问题(在列表中的第一个实际..)http://stackoverflow.com/questions/1787450/how-do-我了解读存储器障碍和易失 – BalusC 2010-04-22 21:02:34

+0

而且我开始关于无序执行的大量“upvotes”和“favorites”volatile的线程:http://stackoverflow.com/questions/2441279/java-volatile-guaranteed-and-of-order-execution – SyntaxT3rr0r 2010-04-22 22:25:07

回答

8

从我所了解的情况来看,总是看起来好像缓存在写入后已经被刷新,并且总是看起来好像在读取时直接从内存读取。其效果是一个线程总是会看到来自另一个线程的写入结果,并且(根据Java内存模型)永远不会有缓存的值。然而,实际的实现和CPU指令会因架构而异。

如果您在多个线程中增加变量,或者检查其值并采取一些操作,则不能保证正确性,因为显然没有实际的同步。如果只有线程写入变量而其他人全部读取,则通常只能保证正确执行。

另请注意,64位非易失性变量可以作为两个32位变量读取/写入,因此32位变量在写入时是原子性的,但是64位变量不是。一半可以写在另一半之前 - 所以读取的值可以是旧的或新的值。

这是从我的书签相当有用的页面:

http://www.cs.umd.edu/~pugh/java/memoryModel/

+2

@jgubby:您的最后一段看起来不正确:您无法读取64位易失性数据,其中一位写32位,另一位写32位。 – SyntaxT3rr0r 2010-04-22 22:28:05

+1

@WizardOfOdds:同意。意思是在那里说非易失性变量。 – gubby 2010-04-23 14:49:22

+0

@jbuggy:啊啊,这就是我的想法,但我不敢编辑你的帖子,因为我不知道你的意思:)很高兴帮助,因为否则它有点混乱:)) – SyntaxT3rr0r 2010-04-23 14:56:25

1

确切地说,会发生什么是处理器特定的。通常有一些形式的记忆障碍指示。刷新整个缓存显然会非常昂贵 - 硬件中存在缓存一致性协议。

同样重要的是,某些优化不是通过字段访问进行的。编译器在考虑多线程时很重要,不要只考虑硬件。

+1

在正确编写的Java程序中发生的事情并不是特定于处理器的。 – gubby 2011-11-01 16:16:29

+0

@jgubby问题确实询问是否发出了特殊说明。 – 2011-11-02 14:17:09