2013-07-18 92 views
1

在C++ 11中,算法是std::random_shuffle線程安全(當由兩個不同容器上的兩個不同線程調用時)?std :: random_shuffle線程安全嗎?

,特別是這種形式:

template <class RandomIt> void random_shuffle(RandomIt first, RandomIt last); 
+2

最有可能不是:'std :: random_shuffle'的重載可能會調用'std :: rand()',它可能使用了一些全局資源。 – juanchopanza

回答

5

函數是線程安全的,如果該函數的兩個併發執行不在相同數據上「工作」。這裏的「工作」意味着沒有任何功能可以以非原子,不一致的方式修改數據。有三種方法如何數據可以由功能進行訪問:

  1. 通過函數的參數,包括由這些參數稱爲經由一個成員函數被稱爲上
  2. 功能靜態的,類的靜態對象
  3. 對象和全局數據,包括被間接調用的函數使用的數據。

由於random_shuffle是一項免費功能,因此2.不適用。然而,該函數具有參數,並且它對它們起作用,因爲它會改變底層序列的內容。但是,如果併發呼叫不對重疊序列進行操作,則不會出現問題。

這留下了靜態/全局數據。大多數隨機數發生器將爲其種子使用某種全局數據。默認的隨機函數rand不需要是線程安全的,並且可能不會顯式同步對其全局種子的訪問。

所以在你的情況下不,它不是線程安全(除非隨機數發生器是)。

你會想要寫一個同步版本的隨機數發生器,並使用不同的發生器併發調用。我寧願使用後者,所以併發洗牌不會干擾彼此的隨機數字序列。 (但我絕不是隨機數字生成專家)。

+0

'rqnd'不是**必須**是線程安全的。這與說**不是**線程安全不一樣。任何特定的實現**都可以使它成爲線程安全的,它的文檔應該告訴你這一點。 –

+0

@PeteBecker *不要求*表示在標準C++中不是線程安全的。如果一個具體的實施提供了比標準要求更多的保證,那就是對標準的擴展。答案是針對一般性的語言問題,而不是針對具體的實施。添加「對特定編譯器來說可能更好」是沒有必要的,因爲它幾乎適用於語言的每個角落,因爲標準明確允許擴展。但是我會改變有關'rand'的措辭:-) –

3

它是線程安全的,如果它使用一個線程安全的隨機數發生器。生成器是實現定義的(如果它使用std::rand,它是否是實現定義的,無論這是否安全),因此您需要查閱所用實現的文檔。可以肯定的是,您應該使用其他變體之一,爲每個線程提供線程安全的生成器或單獨的生成器。