目前,我试图提高对内存障碍,锁和内存模型的理解。
据我所知,有四种不同类型的放松,namley 写 - >读,写 - >写,读 - >写和读 - >读。 x86处理器只允许写 - >读松弛,通常称为总存储顺序(TSO)。 部分存储订单(PSO)允许进一步写入 - >写入放松和轻松存储订单(RSO) 允许以上所有的放松。
此外,存在三种类型的记忆障碍:释放,获取和两者。 锁只能使用获取和释放障碍或有时完全障碍(.Net)。
现在考虑以下示例:
// thread 0
x = 1
flag = 1
//thread 1
while (flag != 1);
print x
我目前的理解告诉我,如果我运行此代码,我不需要额外的内存障碍 TSO机器。 如果它是PSO机器,我需要在x = 1和flag = 1之间的释放屏障以确保 如果flag = 1,则线程1获取x的实际值。 如果它是RSO机器,我需要在while(flag!= 1)之间进一步获取屏障;并打印x以防止 该线程1将x的值读取为早期。
我的观察是否正确?
答案 0 :(得分:0)
我认为您的代码示例接近question
中的代码示例对于RSO来说,你需要比你描述的更多的内存障碍,更具体地说,例如在之前为线程1提供新鲜度保证的内存障碍。
我不确定TSO和PSO部分,希望这可能有所帮助,因为我也试图了解那个问题和几个相关问题中的记忆障碍
答案 1 :(得分:0)
重新排序可能发生在软件(编译器)和硬件级别。所以记住这一点。因此,即使在 TSO CPU 上不会对 2 个存储进行重新排序,也没有什么可以阻止编译器对 2 个存储(或 2 个加载)重新排序。因此,flag
需要是同步变量,flag
的存储需要是发布存储,flag
的负载需要是获取负载。
但是如果我们假设上面的代码代表X86指令:
然后使用 TSO 上面将正常工作,因为它会阻止 2 个商店和 2 个负载被重新排序。
但是对于 PSO,上述操作可能会失败,因为 2 个商店可能会重新排序。
想象一下,您将拥有以下内容:
b = 1
x = 1
flag = 1
其中 b
是与 flag
位于同一缓存行上的值。然后通过写入合并,flag=1
和 b=1
可以合并,因此 flag=1
可以超过 x=1
,因此在 x=1
之前变得全局可见。