java - StoreLoad内存屏障

标签 java multithreading concurrency cpu-architecture java-memory-model

我无法理解 JSR-133 CoookbookStoreLoad 屏障的定义.

Store1; StoreLoad; Load2

StoreLoad barriers protect against a subsequent load incorrectly using Store1's data value rather than that from a more recent store to the same location performed by a different processor.

这是否意味着在没有 StoreLoad 屏障的情况下,处理器可以将 Store1 存储到其写入缓冲区并从其写入缓冲区加载该存储值,即使其他处理器已写入Store1 和 Load1 之间相同的内存位置并刷新到缓存?

最佳答案

是的,这是可能的,具体取决于内存排序模型。

写缓冲区通常是预调度的,这意味着外部世界尚无法观察到其中的存储。然而,为了获得更好的性能,大多数微架构允许在同一线程上执行较年轻的负载,并且如果地址与存储的地址匹配 - 可以执行数据转发以使程序尽可能快地继续,同时使负载看起来好像它是在商店之后完成的。

这对于线程内一致性来说工作得很好,但是当外部处理器访问相同的地址并可能更改数据时,负载可能来不及看到它(尽管在许多 CPU 上,如果负载可能仍然被捕获尚未完成,机器将自行修复)。

我不完全确定引用的意思是什么,但我认为可以用这个场景更好地证明这一点:

CPU0:                              CPU1: 
store [x]<--1                      
                                   store [x]<--2
                                   store [y]<--2
load  r1<--[x]                     
load  r2<--[y]                     

没有障碍的可能结果(理论上)是 r1 == 1, r2 == 2 ,这意味着 CPU1 的两个存储都已经执行(因为我们从 2 读取了 [y]),但不知何故 [x] 的旧值幸存下来(因为它被转发了)。

我不太喜欢这个例子,首先是因为,正如我所说,大多数 CPU 应该成功地监听出该加载的旧值,即使它已执行。其次 - 它过于复杂,因为他们坚持声称:

a StoreLoad is strictly necessary only for separating stores from subsequent loads of the same location(s) as were stored before the barrier

这是错误的,本地址不同时也需要屏障,如以下(经典)示例所示:

CPU0:                              CPU1: 
store [x]<--1                      store [y]<--1
load  r1<--[y]                     load r2<--[x]

这里的地址是不同的,仍然需要一个屏障来防止两个加载都读取旧值的情况(即使必须执行两个存储才能到达那里),这要归功于加载的乱序执行.请注意,这是一个与提出的问题(存储到负载转发)不同的问题,但它证明引用是错误的。

关于java - StoreLoad内存屏障,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21148085/

相关文章:

java - Java 中的抽象工厂模式——填充数组的问题

java - 为什么有两个运行线程而不是一个?

java - BlockingQueue - 仅获取特定对象。

java - 更改 Active Directory 的邮件属性

java - 在同一个Android Studio页面中显示两个listView

java - 如何创建一个递归二叉树,其位序列由给定的前序遍历给出?

java - 媒体应用程序缓冲时间太长

ios - 如何在另一个函数中执行任务并随着任务的进行从那里更新 UI?

Python:鼠标按下时计数,鼠标向上时停止

go - 并发示例混淆