线程安全随机数

时间:2019-03-18 22:33:52

标签: c multithreading numbers random-seed

我在Windows上用C生成随机数时遇到问题。简而言之,我想做的是生成7个0或1的数字。然后函数将这些数字求和,结果将是全局定义数组的索引,并且该索引的值将增加1。生成器函数,我总是得到相同的数字序列。我在做什么错了?

#include <windows.h>
#include <stdio.h>
#include <time.h>

int cells[8];

int generator(int n) {
    int i;
    int sum = 0;

    for (i = 0; i < n; i++) {
        int random_number = rand() % 2 + 0;
        printf("%d ",random_number);
        sum += random_number;

    }
    printf("\n%d\n",sum);
    return sum;
}

DWORD WINAPI ThreadFunc(void *data) {
    cells[generator(7)] =+ 1;
    return 0;
}

int main() {
    srand(time(NULL));
    for (int i = 0; i < 10; ++i) {
        HANDLE thread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);
        WaitForSingleObject(thread, INFINITE);
    }
    for (int j = 0; j < 8; ++j) {
        printf("%i: %i\n", j, cells[j]);
    }
}

2 个答案:

答案 0 :(得分:0)

您不需要线程安全的随机数。您的代码始终以精确的确定性顺序调用rand,因为您在启动下一个线程之前等待每个线程完成。你的问题是这个

cells[generator(7)] =+ 1;

这会将单元格设置为+1,而不是添加一个。

答案 1 :(得分:0)

除了“ this.forName = name; ”问题外,该代码还有其他问题:

Microsoft明确表示种子是特定于线程的(请参见https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/srand):

  

srand函数设置在当前线程中生成一系列伪随机整数的起点。

这意味着种子值(/序列生成器)保存在线程本地存储中。但是,它们指定在创建其他线程之前调用=+ 1会发生什么。因此,在我看来,包含种子值的线程本地存储很可能将从初始化线程中复制-或在您第一次调用srand时,将使用每个线程中的默认种子简单地对其进行重新初始化。如果您根本没有打电话给rand

无论哪种情况,所有线程最终都会产生相同的伪随机序列。

因此,最好调用一次srand,将线程索引添加到该初始时间值,然后将结果作为参数传递给线程函数,然后将该(特定于线程的)值用作time内的 线程的参数。至少每个线程将从不同的初始种子值开始。