6

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

我注意到许多文档建议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 上的互斥锁以防止竞争条件。

4

3 回答 3

2

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

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

  2. 如果你想打srand()几次电话,请不要。这背后的原因是基于种子设置变量的随机生成器初始化例程具有更差的随机特性,提供比随机生成器本身更差的性能,不应用作替代品。

于 2012-11-26T01:36:28.543 回答
1

srand() will reset the stream of numbers rand() will generate for you.

From the manual for 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.

If you need "better" random numbers then rand() provides you should look into other sources of randomness.

Also srand() is not used for rand_r(), the argument you provide (to rand_r()) is used instead.

And if you want to use rand_r() from multiple threads all threads should have a local seed, you shouldn't use a single global variable for that.

Alternatives to rand() can be Mersenne Twister

But if you need "real" randomness you have to look hardware support.

And to answer:

As such, the seed changes once per function call, not once per program. This way, no matter how many threads are running, no two threads will every have the same random number list... Right?

No, doesn't work that way, you should have a thread-local SEED variable initialized to something unique for every thread. You could use time() for the first seed, and then use that random sequence to generate seeds for the other threads, or you read 4-8 bytes from /dev/random or /dev/urandom if you'r using *nix.

Hope that gives some insight as this is midnight rumble, good night <3

于 2012-11-26T01:36:56.197 回答
0

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

于 2012-11-26T01:28:39.263 回答