Потокобезопасное случайное число

У меня проблема с генерацией случайного числа в 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]);
    }
}

Впечатляющая сложность! :-) Кроме того, в строке cells[generator(7)] =+ 1; вы, вероятно, хотели использовать +=.

Chris Olsen 18.03.2019 23:46
stackoverflow.com/questions/52884311/… в принципе та же проблема, и мне лень отвечать на нее еще раз.
nemequ 18.03.2019 23:49

См. Что означает =+ в C?

Jonathan Leffler 19.03.2019 00:39

Ребята, я исправил эту ошибку, но это не моя проблема. Моя проблема заключается в том, что каждый вызов функции печатает одни и те же значения. Например; первая итерация в цикле: 1 1 0 0 1 1 1. Вторая итерация: 1 1 0 0 1 1 1 и так далее. Он всегда дает одинаковые значения.

Zeevac 19.03.2019 00:49
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
257
2

Ответы 2

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

cells[generator(7)] =+ 1;

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

Я пробовал это, но это не проблема. Я все еще получаю те же цифры.

Zeevac 19.03.2019 00:40

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

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

The srand function sets the starting point for generating a series of pseudorandom integers in the current thread.

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

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

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

Другие вопросы по теме