我在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]);
}
}
答案 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
内的 线程的参数。至少每个线程将从不同的初始种子值开始。