std::atomic 将一对原子 int32 视为一个原子 int64?

2024-04-30

我有一对 unsigned int32

std::atomic<u32> _start;
std::atomic<u32> _end;

有时我想通过比较交换来设置开始或结束,因此我不希望在整个 64 位对上使用 CAS 可能导致的虚假故障。我只想使用 32 位 CAS。

_end.compare_exchange_strong(old_end, new_end);

现在我可以将开始和结束作为一个原子 64 位读取来获取。或者两个单独的 32 位读取。执行一次 64 位原子读取(编译器添加适当的内存栅栏)会比使用两个内存栅栏进行两次单独的 32 原子位读取更快(或者编译器会优化它吗?)

如果是这样,我将如何在 c++11 中做到这一点?


该标准并不能保证std::atomics与基础类型具有相同的大小,也不具有相同的操作atomic是无锁的(尽管它们可能是为了uint32至少)。因此我很确定没有任何一致的方法将它们组合成一个64bit原子操作。因此,您需要决定是否要手动将两个变量合并为 64 位变量(并且仅适用于 64 位操作)。

例如,该平台可能不支持64bitCAS(对于第一个 Pentium IIRC 中添加的 x86,因此在编译 486 兼容时将不可用。在这种情况下,它需要以某种方式锁定,因此原子可能包含64bit变量和锁。的

关于围栏:这取决于memory_order您为您的操作指定。如果内存顺序指定两个操作需要按照执行顺序可见,则编译器显然无法优化栅栏,否则可能会。当然假设你只针对 x86memory_order_seq_cst实际上会根据我的记忆发出一个屏障指令,所以任何少的东西都会阻碍编译器完成的指令重新排序,但不会有实际的惩罚)。

当然,根据您的平台,您可能会侥幸治疗两个std::atomic<int32>作为其中之一int64通过以下方式进行铸造union or reinterpret_cast,只是请注意,这种行为不是标准所要求的,并且可以(至少理论上)随时停止工作(新的编译器版本,不同的优化设置,...)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

std::atomic 将一对原子 int32 视为一个原子 int64? 的相关文章

随机推荐