1

我的应用程序需要几个原子加载和存储。不幸的是,这些操作必须发生在内存映射文件中的特定地址,所以我不能使用 c++11 的 std::atomic (因为 std::atomic 通过控制变量的大小和对齐/放置来工作。因为我控制内存映射文件格式,我们只在单个 CPU 架构上运行

有没有办法测试(在运行时)对特定地址的特定大小的读取或写入是否是原子的?我的主要平台是 x86-64,但我也对 ARM 的解决方案感兴趣。

4

1 回答 1

1

简短的回答:可能不会。您可以编写一些代码来更新和检查您的值的有效性,并运行 6 个月。然而,它几乎肯定不能保证代码是正确的——只是你没有找到正确的地方让它出错。

长答案:处理器字的加载和存储几乎可以肯定本身是原子的,但是该std::atomic功能提供了比这更强大的保证。它保证没有处理器会使用“陈旧”的值(缓存一致性和独占更新)。如果没有,您就无法做出同样的保证std::atomic(除非平台本身保证这一点,这可能至少需要它是一个单核处理器)。

在一般情况下,处理器执行的加载和存储具有“弱”缓存一致性和原子更新策略。假设我们有这个代码:

 int a = 42; 
 bool flag = false;

 ... 

 a++;
 flag = true;

和其他一些代码:

 while(!flag)
 a--;

[我目前忽略了flag还需要原子更新策略并且可能需要易变的事实 - 这不是这种情况下的重点]

不能保证编译器不会形成tmp = a; tmp = tmp+1; a = tmp;(并且对应于a--)[可能会在两者之间抛出额外的指令,因为编译器希望以其他方式更快/更好]。

也不能保证该值不会被更新43为缓存内容“乱序”更新)。42flag

x86 处理器肯定是无法保证更新后的值会立即可用的处理器,如上所述。缓存一致性和原子性只是保证你不会读取一些“半生不熟”的值——更新值时它要么是“旧”值,要么是“新”值——但它可能是相当长一段时间内的“旧”值在写入“新”值之后,这通常是“不是一件好事”。

于 2015-03-23T23:32:56.853 回答