由于我认为是比赛条件,我始终编写的小程序被阻止了。有人可以帮助我确定我的错误吗?
有一个功能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
中的条件(等待直到完成多次迭代)是错误的。每当我在Anthony Williams的精彩著作(请参见2012年版4.1.1节)中的示例中使用条件变量时,一个函数就会运行,直到外部条件被否定,但在这里我有两个过程彼此依赖。有人可以指出我可以改善的地方吗?