потокобезопасное случайное число - PullRequest
0 голосов
/ 19 марта 2019

У меня проблема с генерацией случайного числа в C в Windows.Вкратце, я хочу сгенерировать 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 голосов
/ 19 марта 2019

Помимо проблемы "=+ 1" ... есть еще одна проблема с кодом:

Microsoft прямо заявляет, что начальное число зависит от потока (см. https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/srand):

Функция srand устанавливает начальную точку для генерации серии псевдослучайных целых чисел в текущем потоке.

Это означает, что начальное значение (/ генератор последовательности) сохраняется в локальном хранилище потока.Однако они не определяют, что произойдет, если вы вызовете srand перед созданием дополнительных потоков. Поэтому мне представляется весьма вероятным, что локальное хранилище потока, содержащее начальное значение, будет либо скопировано из инициализирующейпоток - или он просто будет повторно инициализирован с начальным значением в каждом потоке при первом вызове rand, как если бы вы не вообще не вызывали srand.

В любом из нихВ этом случае все потоки все равно будут генерировать одну и ту же псевдослучайную последовательность.

Следовательно, вам лучше один раз вызвать time, добавивиндекс потока к этому начальному значению времени, передавая результат в качестве аргумента функции потока, затем используя это (специфичное для потока) значение в качестве аргумента для srand в потоке.По крайней мере, тогда каждый поток будет начинаться с другого начального значения.

0 голосов
/ 19 марта 2019

Вам не нужно потокобезопасное случайное число.Ваш код всегда вызывает rand в точной детерминированной последовательности, потому что вы ждете завершения каждого потока, прежде чем начинать следующий.Ваша проблема заключается в следующем:

cells[generator(7)] =+ 1;

Это устанавливает ячейку на +1, а не добавляет к ней одну.

...