我知道写入volatile
变量会从所有 cpu 的内存中刷新它,但是我想知道对 volatile 变量的读取是否与正常读取一样快?
变量可以volatile
放置在 cpu 缓存中还是总是从主内存中获取?
我知道写入volatile
变量会从所有 cpu 的内存中刷新它,但是我想知道对 volatile 变量的读取是否与正常读取一样快?
变量可以volatile
放置在 cpu 缓存中还是总是从主内存中获取?
你真的应该看看这篇文章:http ://brooker.co.za/blog/2012/09/10/volatile.html 。博客文章认为,易失性读取(对于 x86 也是如此)比 x86 上的非易失性读取要慢得多。
感谢 Marc Booker 运行这些测试。
答案在某种程度上取决于架构。在 x86 上,没有与易失性读取相关的额外开销,尽管对其他优化有影响。
Doug Lea 的 JMM 食谱,请参阅底部附近的架构表。
澄清一下:读取本身没有任何额外的开销。内存屏障用于确保正确排序。JSR-133 将四个屏障分类为“LoadLoad、LoadStore、StoreLoad 和 StoreStore”。根据架构的不同,其中一些障碍对应于“无操作”,这意味着不采取任何行动,而其他障碍则需要围栏。负载本身没有隐含成本,但如果设置了栅栏,可能会产生成本。在 x86 的情况下,只有 StoreLoad 屏障会导致栅栏。
正如博客文章中所指出的,变量是 volatile 的事实意味着无法再对变量的性质进行假设,并且某些编译器优化不会应用于 volatile。
Volatile 不是应该随便使用的东西,但也不应该害怕。在很多情况下,一个 volatile 就足以代替更繁重的锁定。
它依赖于架构。什么volatile
是告诉编译器不要优化该变量。它强制大多数操作将变量的状态视为未知数。因为它是易失的,它可以被另一个线程或其他一些硬件操作改变。因此,读取将需要重新读取变量,并且操作将属于读取-修改-写入类型。
这种变量用于设备驱动程序,也用于与内存中的互斥体/信号量同步。
易失性读取不能那么快,尤其是在多核 CPU(但也只有单核)上。执行核心必须从实际内存地址中获取以确保它获得当前值——该变量确实不能被缓存。
与此处的另一个答案相反,易失性变量不仅仅用于设备驱动程序!它们有时对于编写高性能多线程代码至关重要!
volatile 意味着编译器无法通过将变量值放在 CPU 寄存器中来优化变量。它必须从主存访问。但是,它可以放在 CPU 缓存中。缓存将保证系统中任何其他 CPU/内核之间的一致性。如果内存映射到IO,那么事情就复杂了一些。如果它是这样设计的,硬件将阻止该地址空间被缓存,并且对该内存的所有访问都将转到硬件。如果没有这样的设计,硬件设计人员可能需要额外的 CPU 指令来确保读/写通过缓存等。
通常,“volatile”关键字仅用于操作系统中的设备驱动程序。