2013-07-18 95 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,它是否是实现定义的,无论这是否安全),因此您需要查阅所用实现的文档。可以肯定的是,您应该使用其他变体之一,为每个线程提供线程安全的生成器或单独的生成器。