【发布时间】:2013-02-20 15:45:15
【问题描述】:
如果使用 1 个 volatile 变量,是否也会关闭其他相关非 volatile 变量的 cpu 缓存?
【问题讨论】:
-
为什么像这样的微优化对任何人来说都很重要?我认为这与线程安全有关。
标签: java memory volatile memory-efficient
如果使用 1 个 volatile 变量,是否也会关闭其他相关非 volatile 变量的 cpu 缓存?
【问题讨论】:
标签: java memory volatile memory-efficient
不,它只会阻止该变量被加载到 cpu 缓存并在那里修改。更准确地说,它强制 CPU 在访问 volatile 字段后刷新其缓存。请参阅here 了解更多详细信息
【讨论】:
它不会“关闭”缓存。但是是的,它确实通常会导致其他挂起写入的刷新(当您写入volatile 时)或至少一些缓存失效(当您读取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 happens-before B 和 C happens-before D. 如果线程 2 中的 C 是 随后 中的 B线程 1,然后 B happens-before C,因此 A happens-before D.
如果 A happens-before D 则写入 A 处 bar 的值必须在 D 处作为 bar 可用...假设在此期间没有其他内容写入 bar .
这是具体实现的如何。但肯定会对缓存数据产生影响……包括非易失性字段的缓存副本。
假设一个典型的内存架构,假设线程 1 和线程 2 不共享缓存,这意味着:
foo 和 bar 都必须由 B 处的线程 1 刷新到主内存,并且 foo 和 bar 的任何缓存副本都必须丢弃。我的理解是,这通常是使用缓存失效和缓存刷新指令来实现的。
最重要的是,使用volatile 会对多核系统产生显着的性能影响,因为它会产生额外的内存流量。
【讨论】:
volatile 关键字与内存无关。这是一个并发问题。
编辑 volatile 关键字与内存效率无关。这是一个并发问题。
【讨论】: