非破坏性原子添加?

时间:2014-11-25 13:16:46

标签: c++ multithreading atomic

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

#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的值。有没有办法可以原子地增加测试,而结果不是永久性的?

2 个答案:

答案 0 :(得分:3)

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可能是一个好的开始。

答案 1 :(得分:1)

你可以这样做:

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