【问题标题】:False sharing and volatile虚假共享和易变
【发布时间】:2020-11-06 23:45:12
【问题描述】:

您好,我最近发现了 Java 8 中引入的一个名为 Contended 的注解。从这个邮件list 我了解到什么是错误共享以及注释如何允许对象或字段分配整个缓存行。

经过一些研究,我发现如果两个内核存储相同的缓存行并且其中一个修改它,那么第二个内核必须从主内存重新读取整行。 https://en.wikipedia.org/wiki/MESI_protocol。但我仍然不清楚为什么硬件会强制 CPU 重新读取它。我的意思是这就是为什么我们在 Java 中确实有一个 volatile 关键字,对吧?如果变量被声明为 volatile,那么线程将从缓存中跳过该变量,并始终从主内存读取/写入它。如果硬件在每次写入后强制 cpu 重新读取缓存行,那么在多线程应用程序中如何可能出现数据不一致?
提前致谢

【问题讨论】:

    标签: java caching false-sharing


    【解决方案1】:
    After some research I found that if two cores store the same cache line and 
    one of them modify it then the second one has to reread entire line from main memory. https://en.wikipedia.org/wiki/MESI_protocol.
    

    这是不正确的。缓存是事实的来源,因为缓存(至少在 X86 上)总是一致的。所以理论上缓存线永远不需要从主存中读取;它总是可以从其中一个 CPU 缓存中获得。如果不同的 CPU 缓存需要缓存线,它可以从其他缓存中读取值。使用 MESI,当缓存线处于修改状态并且不同的 CPU 想要读取它时,可能会发生缓存线被刷新到主内存的情况;但否则不需要与主存进行通信。这是因为 MESI 不支持脏共享; MOESI 解决了这个问题。

     But it still unclear for me why hardware forces CPU to reread it. 
     I mean that is why we do have a volatile keyword in Java right ? 
    

    X86 上的缓存总是一致的。为此不需要特殊的 CPU 指令;这是开箱即用的行为。所以它不可能发生,例如值 A=1 被写入某个缓存行,而稍后的读取仍会看到旧值 A=0。

     If variable is declared as volatile then threads will skip this variable 
     from cache and always read/write it from/to main memory. 
     If hardware forces cpu to reread cache lines after every write then how data inconsistency is possible in multi threaded applications?
    

    这是不正确的。缓存是事实的来源;没有“从主存储器强制读取”。有一些特殊指令可以绕过 CPU 缓存,称为非临时加载和存储,但它们与本次讨论无关。

    volatile 的目的是确保相对于其他加载和存储到不同地址的顺序保持不变,并且存储对其他线程可见。

    在虚假分享的情况下;如果 CPU 修改同一缓存线的不同部分,并且一个 CPU 需要写入,而另一个 CPU 刚刚写入它,那么一旦写入命中,第一个 CPU 需要使用 RFO(所有权请求)使另一个 CPU 上的缓存线无效linefillbuffer 并且在此 RFO 被确认之前无法继续写入。但只要其他 CPU 想要写入该缓存行,它就需要发送一个 RFO 并等待确认。

    因此,您会在不同 CPU 之间获得大量缓存一致性流量……不断争夺相同的缓存线。如果运气不好,CPU 不会执行乱序指令,因此即使 CPU 利用率达到 100%,CPU 也基本上会处于空闲状态。

    【讨论】:

    • 感谢这个精彩的解释,它改变了我对 volatile 的看法,直到今天我仍然使用直接来自主存储器的值来实现对 volatile 的原子写入/读取。我仍然不确定“其他线程是否可以看到商店”。那么 volatile 如何使值对其他线程可见,如果缓存是“X86 上的缓存始终是连贯的”,为什么非 volatile 变量不可见。请您分享一些资源,以便我继续研究这个主题
    猜你喜欢
    • 2012-01-10
    • 2019-03-07
    • 2014-03-14
    • 1970-01-01
    • 2015-05-25
    • 2023-03-23
    • 2012-06-17
    • 1970-01-01
    • 2015-07-01
    相关资源
    最近更新 更多