Неправильное использование мьютекса c ++ - PullRequest
0 голосов
/ 28 мая 2020

У меня проблема с кодом. Эта функция помещает товар в очередь.

void producent(bool &cont,std::queue<std::string> &queue,std::mutex &mtx, int &milliseconds)
{
    while (cont)
    {    
        mtx.lock();
        if (queue.size() >= MAX_QUEUE_SIZE)
        {
            mtx.unlock();
            std::cerr << "buffor full " << std::endl;
        }
        else
        {
            std::string product = generate();
            std::cerr << "producent: " << product << " " << std::endl;
            queue.push(product);
            mtx.unlock();
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
    }
}

эта функция генерирует строку из 10 знаков, которые помещаются функцией void producent ().

std::string generate() {
    std::string temp;
    temp.resize(10);
    for (int i = 0; i < 10; i++) {
        temp[i] = rand() % ('z' - 'a' + 1) + 'a';
    }
    return temp;
}

Мой вопрос: почему , когда я создаю 2 потока, например:

std::thread prod(producent, std::ref(wykonuj),std::ref(kolejka), std::ref(kolejka_mtx),std::ref(t));
std::thread prod1(producent, std::ref(wykonuj), std::ref(kolejka), std::ref(kolejka_mtx), std::ref(t));

, оба они дают мне одинаковый результат, например результат:

producent: qweasdzxca
producent: qweasdzxca

Я хотел, чтобы эти результаты были разными, вот и все почему я использовал мьютекс, но он не работал. Может кто-нибудь дать мне совет?

Ответы [ 2 ]

1 голос
/ 28 мая 2020

Предполагая, что ваша реализация имеет потокобезопасный rand() (вероятно, неразумно), оба потока используют одно и то же начальное случайное начальное число (в данном случае значение по умолчанию - 1) и, таким образом, создают одинаковую последовательность. Вместо того, чтобы делать это, используйте предложения C ++ <random>, а также предложения равномерного распределения.

#include <algorithm>
#include <random>
#include <string>

std::string generate(int n=10)
{
    std::mt19937 prng{ std::random_device{}() };
    std::uniform_int_distribution<int> dist('a', 'z');

    std::string result;
    std::generate_n(std::back_inserter(result), n, [&]() { return dist(prng); });
    return result;
}

Выполнено 10x на 10x потоках, это дало:

ysudtdcaeq
hwpeyiyyav
dlsdshltyo
pkfafhooxr
nmoxerbqpy
ydauzdvoaj
brjqjgxrgg
ezdsmbhygb
fpdgbkxfut
elywaokbyv

Это или что-то подобное должно произвести то, что вы ищете.

Примечание: приведенное выше не будет работать должным образом на платформах, где a .. z не является смежным. Если вы пользуетесь таким зверьком (обычно OS / 400 или OS / 390 EBCDI C), вам потребуется альтернативное решение.

1 голос
/ 28 мая 2020

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

Следовательно, generate, вызванный обоими потоками, будет генерировать одну и ту же строку.

В документации предполагается, что rand_r является поточно-ориентированной версией, но обе функции являются поточно-ориентированными в современных реализациях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...