Небольшая программа, которую я написал последовательно, получает блокировку из-за того, что я считаю состоянием гонки.Может ли кто-нибудь помочь мне определить мою ошибку?
Существует одна функция, process_two
, которая выполняет некоторые задачи, а затем использует другую функцию для обновления некоторой базовой структуры данных, прежде чем она может продолжиться. Примечание: эта функция запускается несколькими потоками одновременно Эта функция:
void process_two(int n_tasks) {
while (total_iter < 100) {
// do some work
iter_since_update += n_tasks;
total_iter += n_tasks;
std::shared_lock<std::shared_mutex> lk(mutex);
cv.wait(lk, [&] { return data_updated; });
data_updated = false;
lk.unlock();
}
}
Функция выполняет некоторую работу и увеличивает количество выполненных задач.Затем он получает общую блокировку (если возможно) и ожидает условную переменную.После ожидания поток сбрасывает условие и разблокирует мьютекс.Функция, обновляющая базовую структуру данных:
void process_one(int threshold) {
while (total_iter < 100) {
if (iter_since_update >= threshold) {
std::lock_guard<std::shared_mutex> lk(mutex);
// updating
data_updated = true;
iter_since_update = 0;
cv.notify_all();
}
}
}
Всякий раз, когда другая функция делает некоторое количество итераций, process_one
получает блокировку и обновляет данные.Он также сбрасывает счетчик итераций и уведомляет другие потоки.Наконец, вся программа выглядит так:
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <shared_mutex>
#include <thread>
#include <vector>
int iter_since_update(0);
bool data_updated(true);
std::shared_mutex mutex;
std::condition_variable_any cv;
int total_iter(0);
void process_two(int n_tasks) {
while (total_iter < 100) {
// do some work
iter_since_update += n_tasks;
total_iter += n_tasks;
std::shared_lock<std::shared_mutex> lk(mutex);
cv.wait(lk, [&] { return data_updated; });
data_updated = false;
lk.unlock();
}
}
void process_one(int threshold) {
while (total_iter < 100) {
if (iter_since_update >= threshold) {
std::lock_guard<std::shared_mutex> lk(mutex);
// updating
data_updated = true;
iter_since_update = 0;
cv.notify_all();
}
}
}
int main() {
int total_tasks(10);
int n_threads(1);
int n_tasks = total_tasks / n_threads;
std::thread update_thread([&]() { process_one(total_tasks);});
std::vector<std::thread> threads;
for (int i = 0; i < n_threads; i++)
threads.push_back(std::thread([&]() { process_two(n_tasks); }));
while (total_iter < 100) {
;
}
update_thread.join();
for (int i = 0; i < n_threads; i++) threads[i].join();
}
Я установил общее количество задач и позволил каждому потоку, выполняющему process_two
, выполнить часть этих задач.Всякий раз, когда я устанавливаю n_threads = 1
, программа завершается почти всегда.Всякий раз, когда я устанавливал n_threads = 2
, программа всегда терпела неудачу.
Я новичок в многопоточности в c ++ и буду очень признателен за любые предположения относительно того, что я делаю неправильно.Я подозреваю, что условие в process_one
(ожидание, пока не будет выполнено несколько итераций) неверно.Всякий раз, когда я видел переменные условия, используемые в примерах в замечательной книге Энтони Уильямса (см. Раздел 4.1.1. В редакции 2012 года), одна функция работала до тех пор, пока внешнее условие не будет отменено, но здесь у меня оба процесса зависятдруг на друга.Может кто-нибудь любезно указать, что я могу улучшить?