目前,我正在努力提高对内存屏障、锁和内存模型的理解。
据我所知,存在四种不同类型的松弛,即Write -> Read,Write -> Write,Read -> Write和Read -> Read。x86处理器只允许写入->读取松弛,这通常被称为总存储顺序( Total Store Order )。部分存储顺序(PSO)允许进一步的Write->Write松弛,而宽松存储顺序(RSO)允许所有上述松弛。
此外,还存在三种类型的记忆障碍:释放、获取和两者同时存在。锁可以只使用获取和释放屏障,有时使用完全屏障(.Net)。
现在考虑以下示例:
// thread 0
x = 1
flag = 1
//thread 1
while (flag != 1);
print x我目前的理解告诉我,如果我在TSO机器上运行这段代码,就不需要额外的内存障碍。如果是PSO机,我需要在x=1和flag =1之间设置释放屏障,以确保线程1在flag =1的情况下获得x的实际值。如果是RSO机,我需要在while(flag != 1)和print x之间进一步设置获取屏障,以防止线程1提前读取x的值。
我的观察结果正确吗?
发布于 2011-09-01 10:10:27
我认为您的代码示例与此question中的代码示例非常接近
也就是说,对于RSO,您需要比您所描述的更多的内存屏障,例如,在while之前为线程1提供新鲜性保证的屏障。
我不确定TSO和PSO部分,希望这能有所帮助,因为我也试图理解这个问题中的记忆障碍和一些相关的问题
发布于 2021-03-13 23:14:11
可以在软件(编译器)和硬件级别上进行重新排序。所以请记住这一点。因此,即使在TSO CPU上,这两个存储不会被重新排序,也不会阻止编译器重新排序这两个存储(或两个加载)。所以flag需要是一个同步变量,flag的存储需要是一个释放存储,flag的加载需要是一个获取加载。
但是如果我们假设上面的代码表示X86指令:
然后,使用TSO,上述操作将正常工作,因为它将防止2个存储和2个加载被重新排序。
但使用PSO,上述操作可能会失败,因为这两个商店可能会被重新排序。
因此,想象一下你将拥有以下内容:
b = 1
x = 1
flag = 1由此b是与flag相同的高速缓存线上的值。然后,通过写合并,可以合并flag=1和b=1,因此flag=1可以超过x=1,因此在x=1之前变得全局可见。
https://stackoverflow.com/questions/7146736
复制相似问题