【问题标题】:Java - volatile and visibilityJava - 易失性和可见性
【发布时间】:2016-05-31 20:42:42
【问题描述】:

据我所知,volatile 背后的底层机制保证不会对操作进行重新排序。但是,我很难看到它如何保证可见性。

即线程 A 写入一个值。然后线程 B 从内存中读取它,而不是从缓存中读取(以保证缓存的一致性)。我知道 CAS 正是这样做的,但是内存屏障是如何实现这一点的呢?

【问题讨论】:

    标签: java multithreading volatile


    【解决方案1】:

    内存屏障由 CPU 实现,以始终显示最新值。如果没有 CPU 支持,这是无法实现的。

    一种常见的误解是访问主存,但这会非常慢。相反,L2 缓存之间存在缓存一致性总线。

    在 L1 缓存之前有一个写入存储缓冲区,但 CPU 确保缓存线在内核之间是最新的。

    【讨论】:

    • 是的,但是说“它由 cpub 实现以显示最新值”对我来说有点太高了。它是如何实现的?是否刷新了存储缓冲区?
    • 太笼统和英特尔专用。
    • @Bober02,您好像在问一个关于计算机体系结构的问题,这可能超出了本论坛的范围。
    【解决方案2】:

    易失性“使用”硬件特定指令来实现它。这里是in-depth article about JSR-133 and Memory Barriers for Compiler Writers

    我知道 CAS 正是这样做的,但内存屏障如何实现这一点?

    因为如果您在 AtomicInteger 中查找示例,您会看到

    private volatile int value;
    

    【讨论】:

    • 啊,所以存储缓冲区刷新到主内存和缓存失效...?
    • 是的,并且在加载时缓存“无效” - 这就是传播更改的方式,StoreLoad 屏障。
    【解决方案3】:

    通用内存屏障是特定于 CPU 的指令,表示“使您的读取缓存无效”或“提交您的写入缓存”,或两者兼而有之。在 x86 等强排序 CPU 上,“使读取缓存无效”是无操作的,因为缓存始终是一致的。

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 2017-01-17
      • 1970-01-01
      • 2012-02-22
      • 1970-01-01
      • 1970-01-01
      • 2013-05-23
      • 1970-01-01
      • 2018-01-18
      相关资源
      最近更新 更多