从多个线程使用stdlib的rand()

SIM*_*MEL 41 c c++ random multithreading

我有几个线程都运行相同的功能.在每个中,它们会多次生成不同的随机数.我们尝试通过放置srand(time(0))函数的开头来做到这一点,但似乎它们都得到了相同的数字.

我们是否需要srand(time(0))每个程序只调用一次,即在main(例如)开始时,在每个被调用多次的函数的开头,或者其他什么?

Fré*_*idi 38

srand()播种随机数生成器.你应该只需要srand(time(NULL))在启动时调用一次.

也就是说,文档说明:

该功能rand()不可重入或线程安全的,因为它使用的是在每个调用修改隐藏状态.这可能只是下一次调用要使用的种子值,或者它可能更精细.为了在线程应用程序中获得可重现的行为,必须明确此状态.该函数 rand_r()提供了一个指向an的指针unsigned int,用作状态.这是一个非常少量的状态,所以这个函数将是一个弱的伪随机生成器.请尝试 drand48_r(3).

上面强调的部分可能是你的所有线程获得相同数字的原因.

  • @AnT:但是“rand()”并不*需要*是线程安全的,因此可移植的多线程程序无法安全地使用它(除非用互斥体或类似的东西来保护它)。C17 7.22.2.1p3:“不需要`rand`函数来避免与其他对伪随机序列生成函数[例如其自身]的调用发生数据竞争”。 (4认同)

小智 8

如果您同时启动所有线程,则发送到srand的时间可能与每个线程相同.由于它们都有相同的种子,它们都返回相同的序列.尝试使用其他内容,如本地变量的内存地址.

  • 使用局部变量的内存地址不是一个很好的熵源. (4认同)

Mat*_*Mat 7

rand手册页:

函数rand()不是可重入的或线程安全的,因为它使用在每次调用时修改的隐藏状态.

所以不要将它与线程代码一起使用.使用rand_r(或者drand48_r如果你在linux/glibc上).使每个RNG具有不同的值(您可以在主线程中播种第一个RNG以为每个线程中的那些生成随机种子).


ksh*_*erd 7

当您使用C++而不是C时,您可以通过使用c ++ 11来避免通常与srand/rand相关的线程问题.这取决于使用支持这些功能的最新编译器.您将在每个线程上使用单独的引擎和分发.这个例子就像一个骰子.

#include <random>
#include <functional>

std::uniform_int_distribution<int> dice_distribution(1, 6);
std::mt19937 random_number_engine; // pseudorandom number generator
auto dice_roller = std::bind(dice_distribution, random_number_engine);
int random_roll = dice_roller();  // Generate one of the integers 1,2,3,4,5,6.
Run Code Online (Sandbox Code Playgroud)

在回答这个问题时,我提到了维基百科C++ 11Boost随机.