2014-11-25 104 views
1

如果我有一个原子变量,像这样:非破坏性原子添加?

#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的值。有没有一种方法可以自动增量测试,而不会导致永久性结果?

+3

'another_variable - = 4'? – 2014-11-25 13:23:24

+6

如果在此线程之外没有可见的副作用,那么需要做些什么?关于什么原子? – Useless 2014-11-25 13:25:57

+2

只是'a + 4 2014-11-25 13:30:12

回答

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

+2

std :: atomic ::运算符T()等价于std :: atomic :: load(),所以'if(a + 4 2014-11-25 13:38:56

+0

@JayMiller好点。我个人习惯写'load()',这样我就可以更快地在自己的代码中识别原子,但是为了更好的可读性,当然您的版本可能更适合。 – ComicSansMS 2014-11-25 13:43:02

+2

这取决于您是否在优化“Achtung!Atomics!”或者“嘿,这只是一个数字,现在不用担心你的原子的漂亮的小脑袋”,并且可能因用途而异。 – 2014-11-25 13:46:27

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