为什么rand()在fork之后不是那么随机?

Mr_*_*s_D 10 c random fork

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    int i =10;
    /* initialize random seed:  */
    srand(time(NULL));
    while(i--){
        if(fork()==0){
            /* initialize random seed here does not make a difference:
            srand(time(NULL));
             */
            printf("%d : %d\n",i,rand());
            return;
        }
    }
    return (EXIT_SUCCESS);
}
Run Code Online (Sandbox Code Playgroud)

打印相同(每次运行时不同)数量10次 - 预计?我有一个更复杂的代码片段,每个分叉的进程依次运行 - 没有区别

Dav*_*rtz 18

输出必须相同.如果两个进程每个都使用相同的种子播种随机数并且每次调用rand一次,则它们必须得到相同的结果.这就是拥有种子的重点.所有进程都srand使用相同的种子调用(因为您只调用srand一次)并且它们都调用rand一次,因此它们必须得到相同的结果.

取消注释srand不会产生任何影响,因为除非秒数已经改变,否则他们仍将提供相同的种子.你可以这样做:

srand(time(NULL) ^ (getpid()<<16));
Run Code Online (Sandbox Code Playgroud)


Gre*_*ill 5

rand()函数是伪随机数生成器.这意味着生成的数字序列是确定性的,仅取决于提供的种子.

因为您要将相同的进程分叉10次,所以随机数生成器的状态对于每个子进程都是相同的.下次打电话给rand()你时会得到相同的价值.

通过srand(time(NULL))在子进程内部调用,您可能有所帮助,但粒度time()只有1秒,因此您的所有孩子可能都在同一秒内启动.具有相同值的播种生成相同的伪随机序列.

您可以尝试使用取决于子编号的值进行种子设定:

srand(time(NULL) - i*2);
Run Code Online (Sandbox Code Playgroud)

(我i*2time()fork循环期间前进了1秒的事件.)


Mar*_*ark 5

如果你的代码运行得足够快,srand()可能会为每个fork提供完全相同的时间.time()只会每秒更换一次.