非破坏性原子添加

non-destructive atomic add?

本文关键字:添加 破坏性      更新时间:2023-10-16

如果我有一个这样的原子变量:

#include <atomic>
std::atomic<int> a = 5;

我想原子地检查(a + 4)是否小于另一个变量,而不会覆盖a的原始值:

if(a.something(4) < another_variable){
    //Do not want a to be incremented by 4 at this point
}

我对原子fetch_and_add()++进行了快速测试,它们似乎都增加了可变a的值。有没有办法以原子方式递增进行测试,而结果不是永久性的?

if(a + 4 < another_variable) // ...

这是单个原子所能获得的最好的。您没有数据争用,因为读取原子对并发写入是安全的,并且所有后续操作都发生在原始原子值的副本上。一个更详细但功能等效的版本是:

int const copy_of_a = a.load();
if(copy_of_a + 4 < another_variable) // ...

这也是您在同步方面可以获得的最好的。您可能会担心a可能会在另一个线程上更改为会更改if结果的值。

假设有一个函数以原子方式执行整个操作:

 if(a.plus4IsLessThan(another_variable) // ...

然后,a的并发变化是否及时到达以改变测试结果仍然未知。在同步方面,您没有获得任何额外的保证。

如果这是程序的问题,则表明您需要更强大的同步机制。也许std::mutex将是一个好的开始。

你可以做:

if (a + 4 < another_variable) { ... 

这应该与以下相同:

if (a.load() + 4 < another_variable) { ...

根据定义(§29.6.5/16-17,此处A"指一种原子类型"和"C指其相应的非原子类型"):

A::operator C() const volatile noexcept;
A::operator C() const noexcept;

效果load()

回报load()的结果

两者都不会修改a.