2013-10-16 51 views
3

我有兩個線程linux的C++程序的線程之前寫入全​​局數據 線程A的一些數據寫入一個std ::地圖 沒有其他數據將永遠寫入此地圖 然後線程A創建線程B 線程B從地圖讀取數據當並行線程開始它需要一個互斥訪問產生它

所以在這種情況下,我需要使用Mutex嗎?

如果不是,那麼指定的保證在哪裏。

回答

2

不,互斥量僅在需要同時從兩個或更多線程讀取/寫入存儲器時才需要。 因爲當你有多個線程時,你的std :: map是不可變的,所以你不需要任何同步。 你不需要在不可變數據上使用互斥鎖。 即使在你的情況下,線程B會寫入std :: map,但同時只有一個線程會在這個內存上讀寫,而且你不需要同步一個線程。

+0

您不需要同步,但是您確實需要一個內存屏障,以便先前的寫入在另一個線程中可見。所以這個答案是非常不完整的。 – MSalters

+0

是的,好吧,創建一個新線程會在這種情況下產生這樣的障礙。 – monnoroch

5

編號線程創建是一個同步點,因此在創建第二個線程之前第一個線程產生的所有效果在創建第二個線程時「已經發生」了(以一種可以精確的方式該標準的語言)。

要稍微更精確,在一個線程中創建和後來加入另一個線程的上下文中......

  • 之前的一切線程創建之前發生的線程函數內部什麼,
  • 在線程加入後,線程函數內的所有內容都發生在之前。
+0

提及線程創建的+1作爲同步點,這可能是最關鍵的問題。 – ComicSansMS

1

事實上,占主導地位的格局,只要有可能,應該是:

因此,數據通過使用它的線程所擁有的任務(可變)數據移動。現在,它並不需要「物理」遷移,但使用移動語義使得畫面更加清晰:

#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"; 
} 

注意assertmain中間:併發訪問甚至是不可能的。

查看它Live on Coliru

相關問題