我有兩個線程linux的C++程序的線程之前寫入全局數據 線程A的一些數據寫入一個std ::地圖 沒有其他數據將永遠寫入此地圖 然後線程A創建線程B 線程B從地圖讀取數據當並行線程開始它需要一個互斥訪問產生它
所以在這種情況下,我需要使用Mutex嗎?
如果不是,那麼指定的保證在哪裏。
我有兩個線程linux的C++程序的線程之前寫入全局數據 線程A的一些數據寫入一個std ::地圖 沒有其他數據將永遠寫入此地圖 然後線程A創建線程B 線程B從地圖讀取數據當並行線程開始它需要一個互斥訪問產生它
所以在這種情況下,我需要使用Mutex嗎?
如果不是,那麼指定的保證在哪裏。
不,互斥量僅在需要同時從兩個或更多線程讀取/寫入存儲器時才需要。 因爲當你有多個線程時,你的std :: map是不可變的,所以你不需要任何同步。 你不需要在不可變數據上使用互斥鎖。 即使在你的情況下,線程B會寫入std :: map,但同時只有一個線程會在這個內存上讀寫,而且你不需要同步一個線程。
編號線程創建是一個同步點,因此在創建第二個線程之前第一個線程產生的所有效果在創建第二個線程時「已經發生」了(以一種可以精確的方式該標準的語言)。
要稍微更精確,在一個線程中創建和後來加入另一個線程的上下文中......
提及線程創建的+1作爲同步點,這可能是最關鍵的問題。 – ComicSansMS
事實上,占主導地位的格局,只要有可能,應該是:
與
因此,數據通過使用它的線程所擁有的任務(可變)數據移動。現在,它並不需要「物理」遷移,但使用移動語義使得畫面更加清晰:
#include <map>
#include <string>
using namespace std;
using Map = map<string, int>;
Map worker(Map&& data)
{
for (auto& el : data)
el.second *= -1;
return std::move(data);
}
#include <cassert>
#include <iostream>
#include <future>
int main()
{
Map global
{ { "one", 1 },
{ "two", 2 },
{ "three", 3 } };
auto background = async(worker, std::move(global));
assert(global.empty()); // data now owned by the worker thread!
global = background.get(); // await the result from the worker
for (auto const& el: global) // now the data is owned by the main thread
std::cout << el.first << ": " << el.second << "\n";
}
注意assert
在main
中間:併發訪問甚至是不可能的。
查看它Live on Coliru。
您不需要同步,但是您確實需要一個內存屏障,以便先前的寫入在另一個線程中可見。所以這個答案是非常不完整的。 – MSalters
是的,好吧,創建一個新線程會在這種情況下產生這樣的障礙。 – monnoroch