[英]C++ 11 can you safely pass and access std::atomics by reference in different threads
我想知道您是否可以通過引用線程來傳遞原子,並且.load和.store操作仍然是線程安全的。 例如:
#include <thread>
#include <atomic>
#include <cstdlib>
void addLoop(std::atomic_int& adder)
{
int i = adder.load();
std::srand(std::time(0));
while(i < 200)
{
i = adder.load();
i += (i + (std::rand() % i));
adder.store(i);
}
}
void subLoop (std::atomic_int& subber)
{
int j = subber.load();
std::srand(std::time(0));
while(j < 200)
{
j = subber.load();
j -= (j - (std::rand() % j));
subber.store(j);
}
}
int main()
{
std::atomic_int dummyInt(1);
std::thread add(addLoop, std::ref(dummyInt));
std::thread sub(subLoop, std::ref(dummyInt));
add.join();
sub.join();
return 0;
}
如果subLoop要使用load和store函數訪問它,那么當addLoop線程將新值存儲到原子中時,它最終將處於未定義狀態嗎?
根據[介紹種族] /20.2,
如果程序的執行包含兩個潛在的並發沖突操作,其中至少一個不是原子操作,並且沒有一個先於另一個發生,則執行該程序將導致數據爭用,除了以下所述的信號處理程序的特殊情況。 任何此類數據爭用都會導致未定義的行為。
根據[介紹種族] / 2,
如果兩個表達式求值中的一個修改內存位置(4.4),而另一個表達式讀取或修改相同的內存位置,則這兩個表達式求值會發生沖突。
通過引用訪問原子變量不會引入任何其他訪問或修改,因為引用不會占用內存位置。 因此,當潛在的並發原子操作通過引用發生時,仍然是安全的。
實際上,在C ++中的抽象評估模型中,按對象名稱訪問對象和通過綁定到該對象的引用變量訪問對象之間沒有區別。 兩者都只是引用對象的左值。
注意非原子的std::atomic_init
函數:
std::atomic<int> x;
void f(std::atomic<int>& r) {
std::atomic_init(&r, 0);
}
void g(std::atomic<int>& r) {
r = 42;
}
在上面的代碼中,如果f
和g
在單獨的線程中運行並且都訪問原子變量x
,則可能發生數據爭用,因為其中一個操作不是原子操作。 但是,這與觸發數據競爭沒有什么不同,如下所示:
std::atomic<int> x;
void f() {
std::atomic_init(&x, 0);
}
void g() {
x = 42;
}
沒有參考的地方。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.