【发布时间】:2016-05-20 11:46:05
【问题描述】:
StoreStore Barriers 序列:Store1;商店商店; Store2 确保 Store1 的数据对其他处理器可见(即刷新到 内存)之前与 Store2 关联的数据和所有后续 存储说明。一般来说,需要 StoreStore 屏障 不保证刷新的严格顺序的处理器 从写缓冲区和/或缓存到其他处理器或主内存。
而且,从说明书中我们知道,对于同步块,Java 编译器会插入一些障碍来防止可能的重新排序:
MonitorEnter
[LoadLoad] <==inserted barrier
[LoadStore]<==inserted barrier
...
[LoadStore]<==inserted barrier
[StoreStore]<==inserted barrier
MonitorExit
但是,由于 x86 不允许重新排序 Read-Read、Read-Write 和 Write-Write。所以上面所有的barrier都会映射到no-ops。也就是说对于x86处理器来说MonitorEnter和MonitorExit之间不会插入barrier。 我的困惑是,如果我们将 StoreStore 映射到 x86 下的 no-op,那么如何保证可见性? 更详细地说,x86 确实使用了存储缓冲区,因此为了使在关键部分执行的写入对其他处理器可见,我们需要刷新存储缓冲区,因此需要写入屏障。从可见性的角度来看,a 应该映射到 sfence/mfence/Lock#?但是食谱说,从防止重新排序的角度来看,它应该映射到无操作。 或者,关键是可见性保证是由 MonitorEnter 完成的,并且 MonitorExit 本身?如果是这样的话,我想他们可能会使用所谓的 Read barrier 和 Write barrier 来保证可见性,对吧?
【问题讨论】:
-
x86 自己的内存模型已经保证所有写入都具有 StoreStore 语义,因此您不必显式提供屏障。这很常见(在 AArch64 上,CAS 实现方面不需要显式障碍,使用的指令提供了您需要的所有保证),尽管 x86 通常提供现代 IS As 的最强保证,因此您根本不需要显式障碍。
-
谢谢@Voo,也许我的问题可以概括为:在x86下,如果我们将StoreStore映射到no-op(因为x86不允许Write-Write的重新排序)以防止重新排序,那么为了保证可见性,我们可能会将 StoreStore 映射到 sfence/mfence/LOCK 前缀指令。这似乎很奇怪,对吧?
-
x86 上的存储为您提供所需的可见性保证。关于刷新存储缓冲区:确实是必要的(好吧或具有相同效果的类似内容 - 实现细节和所有内容),但这就是 StoreLoad 屏障所做的 - 在 x86 上需要这些。正是出于这个原因,它们也是最昂贵的。
标签: java multithreading