【问题标题】:thread safe random number线程安全随机数
【发布时间】:2019-08-09 09:26:13
【问题描述】:

我有一个关于在 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]);
    }
}

【问题讨论】:

  • 令人印象深刻的复杂性! :-) 另外,在cells[generator(7)] =+ 1; 行中,您可能打算使用+=
  • stackoverflow.com/questions/52884311/…基本是同一个问题,懒得再回答了。
  • 伙计们,我纠正了这个错误,但这不是我遇到的问题。我的问题是函数的每次调用,它都会打印相同的值。例如;循环中的第一个迭代:1 1 0 0 1 1 1。第二个迭代:1 1 0 0 1 1 1 等等。它总是给出相同的值。

标签: c multithreading numbers random-seed


【解决方案1】:

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

cells[generator(7)] =+ 1;

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

【讨论】:

  • 我试过了,但这不是问题。我仍然得到相同的数字。
【解决方案2】:

除了“=+ 1”问题......代码还有一个额外的问题:

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

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

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

在任何一种情况下,所有线程最终都会生成相同的伪随机序列。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-14
    • 2020-01-31
    • 1970-01-01
    • 2012-02-07
    • 2014-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多