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