10

像在 Java 中那样标记变量volatile可确保每个线程都看到上次写入它的值,而不是某个陈旧的值。我想知道这实际上是如何实现的。JVM 是否发出特殊指令来刷新 CPU 现金或其他什么?

4

2 回答 2

10

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

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

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

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

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

于 2010-04-22T21:05:17.503 回答
1

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

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

于 2010-04-22T21:05:16.070 回答