下面的代码会自动执行吗?
const int oldId = id.exchange((id.load()+1) % maxId);
其中id
是std::atomic<int>
,而maxId
是某个整数值。
我在google和stackoverflow上搜索了std::atomic
模增量,我找到了一些主题,但是我找不到明确的答案,如何正确地做到这一点。
在我的情况下,更好的方法是用途:
const int newId = id.exchange((++id) % maxId);
但我仍然不确定它是否会被原子地执行。
1条答案
按热度按时间4bbkushb1#
不,这不是原子操作,因为
load()
和exchange()
是独立的操作,没有什么可以阻止id
在load
之后、exchange
之前更新,在这种情况下,exchange
将写入一个基于过时输入计算的值,因此您最终会错过更新。您可以使用一个简单的compare_exchange循环来实现模增量:
如果compare_exchange失败,它会执行重新加载并使用更新后的值填充
val
,因此我们可以重新计算newVal
并重试。编辑:
比较-交换-循环的全部意义在于处理在加载和比较-交换之间可能有人更改
id
的情况。1.加载
id
的当前值1.计算新值
1.用我们自己的值更新
id
* 当且仅当 * 当前存储在id
中的值与我们在1中读取的值相同。如果是这种情况,我们就完成了,否则我们从1重新开始。compare_exchange允许我们在一个原子操作中执行比较和条件更新。
compare_exchange
的第一个参数是期望值(我们在比较中使用的值)。该值通过引用传递。因此,当比较失败时,compare_exchange
自动重新加载当前值并更新提供的变量(在我们的示例中为val
)。由于Peter Cordes正确地指出,这可以在do-while循环中完成,以避免代码重复,因此如下所示: