我的应用程序需要几个原子载荷和存储。不幸的是,这些操作必须发生在内存映射文件中的特定地址,所以我不能使用c ++ 11的std :: atomic(因为std :: atomic通过控制变量的大小和对齐/位置来工作)由于我控制了内存映射文件格式,我们只运行在一个单独的CPU架构上,我只是查看了目标的对齐和大小限制,并排列了允许原子性的东西(包括在正确位置的完整围栏)。
有没有办法测试(在运行时)特定大小的特定大小的读取或写入是否是原子的?我的主要平台是x86-64,但我也对ARM的解决方案感兴趣。
答案 0 :(得分: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
,但其他代码在退出循环后已读取旧42
值,因为flag
为是的(因为处理器没有按照您期望的顺序执行所有操作,并且缓存内容会“无序”更新。)