随机数和多个srand调用

我正在编写一个程序,它将在循环中生成大量随机数。 我试图使这些数字更难以预测(不仅是为了安全,而是为了避免multithreading上的冲突)。

我注意到许多文档建议在程序中只调用一次srand 。 例如: C中的随机数 ,选择的答案是“作为一般规则,只在程序中调用一次srand()”。

但为什么? 做这样的事情为什么会这么糟糕:

 int THIS_THREAD_SEED; int randomness() { ++THIS_THREAD_SEED; int i; for(i=0 i<1000; i++) { unsigned n = rand_r(&THIS_THREAD_SEED) / RAND_MAX; /* do something with n */ } return 0; } int do_something() { int i; for(i=0; i<1000; i++) { randomness(); } } 

因此,每个函数调用一次更改种子,而不是每个程序一次。 这样,无论有多少线程在运行,没有两个线程都会有相同的随机数列表……对吗?

更新假设我为每个线程都有一个唯一的种子,或者在全局SEED上使用互斥锁来防止竞争条件。

让我们把这个问题分成两个单独的问题。

  1. 如果您在访问随机数生成器时担心竞争条件,请创建互斥或其他同步原语以避免这种情况。

  2. 如果你想多次调用srand() ,请不要。 这背后的原因是随机生成器初始化例程,它根据种子设置变量具有更差的随机特性,比随机生成器本身的性能更差,不应该用作替代品。

srand()重置 rand()将为您生成的数字流。

从srand的手册:

  The srand() function sets its argument as the seed for a new sequence of pseudo-random integers to be returned by rand(). These sequences are repeatable by calling srand() with the same seed value. 

如果你需要“更好”的随机数,那么rand()提供你应该查看其他随机来源。

另外srand()不用于rand_r() ,而是使用你提供的参数(对rand_r() )。

如果你想从多个线程使用rand_r() ,所有线程都应该有一个本地种子,你不应该使用一个全局变量。

rand()替代品可以是Mersenne Twister

但是如果你需要“真正的”随机性,你必须寻找硬件支持。

并回答:

因此,每个函数调用一次更改种子,而不是每个程序一次。 这样,无论有多少线程在运行,没有两个线程都会有相同的随机数列表……对吗?

不,不这样做,你应该有一个线程局部的SEED变量初始化为每个线程独特的东西。 您可以对第一个种子使用time() ,然后使用该随机序列为其他线程生成种子,或者如果使用* nix,则从/dev/random/dev/urandom读取4-8个字节。

希望能给出一些见解,因为这是午夜隆隆声,晚安<3

为避免竞争条件,您需要为每个线程使用单独的种子变量。 这意味着每个线程都有自己独立的随机数序列。