挥发性如何实际起作用?

时间:2010-04-22 20:58:44

标签: java concurrency volatile

在Java中将变量标记为volatile可确保每个线程都能看到上次写入的值而不是某些过时值。我想知道这是如何实现的。 JVM是否发出特殊指令来刷新CPU内存或其他内容?

2 个答案:

答案 0 :(得分:9)

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

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

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

这是我的书签中非常有用的页面:

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

答案 1 :(得分:1)

究竟发生了什么是特定于处理器的。通常存在某种形式的存储器屏障指令。刷新整个缓存显然非常昂贵 - 硬件中存在缓存一致性协议。

同样重要的是,不会在现场访问中进行某些优化。在考虑多线程时,编译器很重要,不要只考虑硬件。