C ++ потокобезопасная вставка вектора - PullRequest
1 голос
/ 17 марта 2020

Несколько потоков обрабатывают данные, и в конце все они вставляют / добавляют результаты в вектор RESULT.
Я хочу убедиться, что только один поток вставляет элементы в вектор RESULT одновременно.
Для этого я использовал mutex и lock_guard (), но иногда они выдают ошибку неверного доступа, а иногда нет ...
Вот мой код для синхронизации

void insert_output() {
    mutex m;
    lock_guard<mutex> lockGuard(m);
    Resources::results.insert(Resources::results.begin(), output.begin(), output.end());
}

Я что-то не так делаю ...
А как лучше синхронизировать этот процесс?

Ответы [ 3 ]

3 голосов
/ 17 марта 2020

Должен быть только один мьютекс для вектора. Поэтому вы должны добавить мьютекс рядом с вектором, например, как results_mutex в Resources. Если results является членом stati c, то мьютекс должен быть также членом stati c (так что для вектора существует только один мьютекс).

Тогда вы также должны заблокировать мьютекс на всех операциях с доступом к вектору, которые потенциально могут выполняться параллельно с вызовом insert_output, а не only для операции вставки.

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

2 голосов
/ 17 марта 2020

С небольшим улучшением спецификации это становится довольно простым. Если у вас есть n потоков, каждый из которых создает m результатов, просто создайте свой вектор с n*m элементами, и каждый поток скопирует свои результаты в соответствующий поддиапазон. Таким образом, поток j копирует свои результаты в results[j*m] через results[j*m + m - 1]. Синхронизация не требуется, поскольку ни один из потоков не изменяет одновременно один и тот же элемент.

В целом, если вы заранее знаете, сколько результатов создаст каждый поток, вы можете соответствующим образом расположить вектор результатов так, чтобы их не было. конфликтующие записи.

1 голос
/ 17 марта 2020

вам нужно сделать мьютекс на один экземпляр, он делает блокировку на экземпляр.

mutex m;
void insert_output() {
    lock_guard<mutex> lockGuard(m);
    Resources::results.insert(Resources::results.begin(), output.begin(), output.end());
}
...