如果数据竞争不是问题,我可以使用std::condition_variable启动(即信令)和停止(即等待)线程的工作吗?
例如:
std::atomic<bool> quit = false;
std::atomic<bool> work = false;
std::mutex mtx;
std::condition_variable cv;
// if work, then do computation, otherwise wait on work (or quit) to become true
// thread reads: work, quit
void thread1()
{
while ( !quit )
{
// limiting the scope of the mutex
{
std::unique_lock<std::mutex> lck(mtx);
// I want here is to wait on this lambda
cv.wait(lck, []{ return work || quit; });
}
if ( work )
{
// work can become false again while working.
// I want here is to complete the work
// then wait on the next iteration.
ComputeWork();
}
}
}
// work controller
// thread writes: work, quit
void thread2()
{
if ( keyPress == '1' )
{
// is it OK not to use a mutex here?
work = false;
}
else if ( keyPress == '2' )
{
// ... or here?
work = true;
cv.notify_all();
}
else if ( keyPress == ESC )
{
// ... or here?
quit = true;
cv.notify_all();
}
}Update/Summary:不安全,因为亚当描述的“失去唤醒”场景。cv.wait(lck, predicate());可以等效为while(!predicate()){ cv.wait(lck); }。
要更容易地看到问题:while(!predicate()){ /*lost wakeup can occur here*/ cv.wait(lck); }
可以通过将谓词变量的任何读/写放到互斥范围中来修复:
void thread2()
{
if ( keyPress == '1' )
{
std::unique_lock<std::mutex> lck(mtx);
work = false;
}
else if ( keyPress == '2' )
{
std::unique_lock<std::mutex> lck(mtx);
work = true;
cv.notify_all();
}
else if ( keyPress == ESC )
{
std::unique_lock<std::mutex> lck(mtx);
quit = true;
cv.notify_all();
}
}发布于 2021-04-08 01:33:00
不,不安全。等待的线程可以获取互斥对象,检查谓词,看不到需要唤醒的任何内容。然后,信令线程设置bool,并发出信号。接下来,等待线程在cv上阻塞,并且永远不会唤醒。
您必须在触发唤醒lambda条件和通知cv之间的某个点保持互斥锁,以避免出现这种情况。
我没有看过的“向下”(关闭唤醒)的情况,这可能取决于什么行为到底是好的。如果没有在正式意义上指定的内容,我也不会这么做;一般来说,在处理多线程代码时,您至少应该尝试对正确性的正式证明草图,否则您的代码最多只会意外地工作。
如果你不能这样做,找一个可以为你编写代码的人。
https://stackoverflow.com/questions/66995664
复制相似问题