2017-04-01 23 views
0

rand()は「スレッドセーフ」でなく、毎回異なるシード値を使用するため、使用しないように頼まれました。わずか数秒で精度を持つrand_r()を使ってCでスレッドセーフな乱数生成器を作成するには?

unsigned int seed = time(NULL);

:私はこのようなシード値を使用してGitHubの上の例を見つけました。プログラムは1秒未満で実行されるので、インスタンスごとに同じ乱数を得ることになります。

rand_r()または他の「スレッドセーフ」メソッドを使用して10個の乱数を生成するように、このアルゴリズムを修正する方法を教えてください。

int main() 
{ 
    for(int i = 0; i < 10; i++){ 
     int random; 
     unsigned int seed = time(NULL); 
      random = 1 + (rand_r(&seed)% 10); 
     printf("%d\n",random); 
    } 
return 0; 
} 
+1

ように多くの類似した質問と同じように - 唯一のシード**度**。 –

+0

Huh..odd。何度もシーディングを行うと、数字が正確に同じになるのですか? – btramisetty

+2

'rand_r'は一つの引数を持つ確定的な関数なので、' seed'の値です。 –

答えて

0

rand_r関数は、状態変数へのポインタをとります。これは、最初にrand_rが呼び出される前にシード値に設定されます。その後、rand_rに電話するたびに、この値のアドレスを渡します。

スレッドセーフであるためには、スレッドごとに独自の状態変数が必要です。ただし、各スレッドの状態変数に同じ初期値を使用する必要はありません。そうでなければ、すべてのスレッドは同じシーケンスの疑似ランダム値を生成します。

ステート変数には、スレッドIDや時刻やPIDなどの他の情報など、スレッドごとに異なるデータをシードする必要があります。例えば

// 2 threads, 1 state variable each 
unsigned int state[2]; 

void *mythread(void *p_mystate) 
{ 
    unsigned int *mystate = p_mystate; 
    // XOR multiple values together to get a semi-unique seed 
    *mystate = time(NULL)^getpid()^pthread_self(); 

    ... 
    int rand1 = rand_r(mystate); 
    ... 
    int rand2 = rand_r(mystate); 
    ... 
    return NULL; 
} 

int main() 
{ 
    pthread_t t1, t2; 

    // give each thread the address of its state variable 
    pthread_create(&t1, NULL, mythread, &state[0]); 
    pthread_create(&t2, NULL, mythread, &state[1]); 
    ... 
    pthread_join(t1, NULL); 
    pthread_join(t2, NULL); 
    return 0; 
}