使用单个条件变量暂停多个线程
Posted
技术标签:
【中文标题】使用单个条件变量暂停多个线程【英文标题】:Using a single Condition Variable to pause multiple threads 【发布时间】:2018-11-13 00:01:09 【问题描述】:我有一个启动 N 个线程(异步/未来)的程序。我想让主线程设置一些数据,然后所有线程都应该去,而主线程等待所有其他线程完成,然后这需要循环。
我的atm是这样的
int main()
//Start N new threads (std::future/std::async)
while(condition)
//Set Up Data Here
//Send Data to threads
std::lock_guard<std::mutex> lock(mrun);
bRun = true;
run.notify_all();
//Wait for threads
std::unique_lock<std::mutex> lock(mrun);
run.wait(lock, [] return bDone; );
//Reset bools
bRun = false;
bDone = false;
//Get results from futures once complete
int thread()
while(otherCondition)
std::unique_lock<std::mutex> lock(mrun);
run.wait(lock, [] return bRun; );
bDone = true;
//Do thread stuff here
lock.unlock();
run.notify_all();
但是我看不到任何主线程或其他线程在等待对方的迹象!知道我做错了什么或者我该怎么做吗?
【问题讨论】:
【参考方案1】:有几个问题。首先,您将在第一个工作人员醒来时设置bDone
。因此主线程立即唤醒并开始准备下一个数据集。您想让主线程等待,直到所有工作人员完成处理他们的数据。其次,当工作人员完成处理时,它会循环并立即检查bRun
。但它无法判断bRun == true
是否意味着下一个数据集已准备就绪,或者 last 数据集是否已准备好。您想等待下一个数据集。
这样的事情应该可以工作:
std::mutex mrun;
std::condition_variable dataReady;
std::condition_variable workComplete;
int nCurrentIteration = 0;
int nWorkerCount = 0;
int main()
//Start N new threads (std::future/std::async)
while(condition)
//Set Up Data Here
//Send Data to threads
std::lock_guard<std::mutex> lock(mrun);
nWorkerCount = N;
++nCurrentIteration;
dataReady.notify_all();
//Wait for threads
std::unique_lock<std::mutex> lock(mrun);
workComplete.wait(lock, [] return nWorkerCount == 0; );
//Get results from futures once complete
int thread()
int nNextIteration == 1;
while(otherCondition)
std::unique_lock<std::mutex> lock(mrun);
dataReady.wait(lock, [&nNextIteration] return nCurrentIteration==nNextIteration; );
lock.unlock();
++nNextIteration;
//Do thread stuff here
lock.lock();
if (--nWorkerCount == 0)
lock.unlock();
workComplete.notify_one();
请注意,此解决方案并不完整。如果一个worker遇到异常,那么主线程就会挂起(因为死掉的worker永远不会减少nWorkerCount
)。您可能需要一种策略来处理这种情况。
顺便说一下,这种模式称为barrier
。
【讨论】:
以上是关于使用单个条件变量暂停多个线程的主要内容,如果未能解决你的问题,请参考以下文章