2

目前我试图提高我对内存屏障、锁和内存模型的理解。

据我所知,存在四种不同类型的放松,namley Write -> Read,Write -> Write,Read -> Write 和 Read -> Read。x86 处理器只允许写入->读取松弛,这通常称为总存储顺序 (TSO)。部分存储顺序 (PSO) 允许进一步的写入->写入松弛,而松弛存储顺序 (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); 之间进一步设置一个获取障碍;并打印 x 以防止线程 1 提前读取 x 的值。

我的观察正确吗?

4

2 回答 2

0

我认为您的代码示例在这个问题中接近一个

也就是说,对于 RSO,您需要比您描述的更多的内存屏障,更具体地说,例如在 while 之前为线程 1 提供新鲜度保证的内存屏障。

我不确定 TSO 和 PSO 部分,希望这会有所帮助,因为我也试图了解该问题中的内存障碍以及一些相关问题

于 2011-09-01T02:10:27.467 回答
0

重新排序可以发生在软件(编译器)和硬件级别。所以记住这一点。因此,即使在 TSO CPU 上 2 个存储不会重新排序,也没有什么可以阻止编译器重新排序 2 个存储(或 2 个加载)。所以flag需要是一个同步变量,存储flag需要是释放存储,负载flag需要是获取负载。

但是如果我们假设上面的代码代表 X86 指令:

然后使用 TSO,上述操作将正常工作,因为它会阻止 2 个存储和 2 个负载被重新排序。

但是对于 PSO,上述操作可能会失败,因为可以重新订购 2 家商店。

因此,想象一下您将拥有以下内容:

b = 1
x = 1
flag = 1

其中b是与 相同的高速缓存行上的值flag。然后通过写入合并,flag=1andb=1可以合并,因此flag=1可以超越x=1,因此在 . 之前变得全局可见x=1

于 2021-03-13T15:14:11.000 回答