2

如果使用 1 个易失性变量,它是否也会关闭其他相关非易失性变量的 cpu 缓存?

4

3 回答 3

2

不,它只会阻止该变量被加载到 cpu 缓存并在那里修改。更准确地说,它强制 CPU 在访问 volatile 字段后刷新其缓存。有关更多详细信息,请参见此处

于 2013-02-20T15:47:29.263 回答
1

它不会“关闭”缓存。但是,是的,它通常会导致其他挂起写入的刷新(当您写入 a 时volatile)或至少一些缓存失效(当您读取 a 时volatile)......并且这两者都使用额外的内存带宽,并影响性能。

考虑这个例子:

public volatile int foo;
public int bar;

/* thread 1 */

bar = 1; // A
foo = 1; // B

/* thread 2 */
System.err.println("foo = " + foo);  // C
System.err.println("bar = " + bar);  // D

JLS 说 A发生在B 之前,C发生在D 之前。如果线程 2 中的 C 在线程 1 中的 B之后,则 B发生在C 之前,因此 A发生在D之前。

如果 A发生在D 之前,则在 A 处写入的值bar必须bar在 D 处可用……假设bar在此期间没有其他内容写入。

具体如何实现这一点是特定于实现的。但肯定会对缓存数据产生影响……包括非易失性字段的缓存副本。

假设一个典型的内存架构,并假设线程 1 和线程 2 不共享缓存,这意味着:

  • 两者都foo必须bar由 B 处的线程 1 刷新到主内存,并且
  • foo在 C 处,任何线程 2 的和的缓存副本都bar必须被丢弃。

我的理解是,这通常是使用缓存无效和缓存刷新指令来实现的。


最重要的是,由于它会产生额外的内存流量,因此使用volatile可能会对多核系统产生重大的性能影响。

于 2013-02-20T15:49:22.407 回答
0

volatile 关键字与内存无关。这是一个并发问题。

编辑 volatile 关键字与内存效率无关。这是一个并发问题。

于 2013-02-20T15:50:34.077 回答