【问题标题】:Is std::random_shuffle thread safe? [duplicate]std::random_shuffle 线程安全吗? [复制]
【发布时间】:2013-07-18 10:12:54
【问题描述】:

在 C++11 中,算法 std::random_shuffle 线程安全吗(当被两个不同容器上的两个不同线程调用时)?

尤其是这种形式:

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

【问题讨论】:

  • 很可能不会:std::random_shuffle 的重载可能会调用 std::rand(),这可能会使用一些全局资源。

标签: c++ c++11 random thread-safety shuffle


【解决方案1】:

如果该函数的两个并发执行不在同一数据上“工作”,则该函数是线程安全的。这里的“工作”意味着没有一个函数可以以非原子、不一致的方式修改数据。函数可以通过三种方式访问​​数据:

  1. 通过函数参数,包括这些参数引用的对象
  2. 通过对象调用成员函数
  3. 函数静态、类静态和全局数据,包括间接调用的函数使用的数据。

由于random_shuffle 是免费函数,2. 不适用。然而,该函数具有参数,并且它在改变底层序列内容的意义上对它们起作用。但是如果并发调用不对重叠的序列进行操作就没有问题。

剩下的是静态/全局数据。大多数随机数生成器将使用某种全局数据作为其种子。默认随机函数rand 不需要是线程安全的,并且可能不会显式同步对其全局种子的访问。

所以在你的情况下不,它不是线程安全的(除非随机数生成器是)。

您可能想要编写随机数生成器的同步版本,或者在并发调用中使用不同的生成器。我更喜欢使用后者,所以并发洗牌不会干扰彼此的随机数序列。 (但我绝不是随机数生成方面的专家)。

【讨论】:

  • rqnd 不是必需线程安全的。这与说它是 not 线程安全的不同。任何特定的实现都可以使它成为线程安全的,它的文档应该告诉你这一点。
  • @PeteBecker 不需要 意味着在标准 C++ 中不是线程安全的。如果一个特定的实现提供了比标准要求更多的保证,那就是对标准的扩展。答案是针对一般语言问题,而不是针对特定实现。添加“在您的特定编译器上可能会更好”是不必要的,因为它几乎适用于语言的每个角落,因为标准明确允许扩展。但我会稍微改变一下rand 的措辞:-)
【解决方案2】:

如果它使用线程安全的随机数生成器,它就是线程安全的。生成器是实现定义的(如果它使用std::rand,那么它是否安全也是实现定义的),因此您需要查阅您正在使用的实现的文档。

当然,您应该使用其他变体之一,为每个线程提供线程安全生成器或单独的生成器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-23
    • 2017-05-08
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    • 1970-01-01
    • 2010-11-24
    相关资源
    最近更新 更多