随机数和多个srand调用

时间:2012-11-26 01:11:50

标签: c random srand

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

我注意到许多文档建议在程序中只调用一次srand。例如:Random numbers in 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上使用互斥量来防止竞争条件。

3 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:1)

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()作为第一个种子,然后使用该随机序列为其他线程生成种子,或者如果您是/dev/random/dev/urandom,则读取4-8个字节使用* nix。

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

答案 2 :(得分:0)

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