2014-11-25 98 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