std :: condition_variable仅在调试时有效吗? [英] std::condition_variable only works while debugging?
问题描述
我用C ++ 14编写了一个项目,该项目是使用Intel的icpc在Fedora 26(gcc 7依赖项)上编译的。一切都很好,并且运转良好,直到我将项目移至Centos 7并开始经历非常神秘的行为。
I wrote a project in C++14, compiled with Intel's icpc on Fedora 26 (gcc 7 dependency). Everything was good and working, until I moved my project onto Centos 7, and began experiencing very mysterious behavior.
在Centos上(scl启用devtoolset-7 bash),源代码可以正确编译和链接,但是该项目仅在使用GDB调试时有效。如果不进行调试,则条件变量的唤醒睡眠线程的通知将不起作用。
On Centos (scl enable devtoolset-7 bash), source code compiles and links without error, but the project only works while debugging with GDB. Without debugging, the condition variable's notification to wake up a sleeping thread don't function.
多个工作线程进入睡眠状态,但通知不起作用,并且它们不起作用不醒。但是使用GDB运行,一切正常。
Multiple worker threads go to sleep, but notification doesn't work, and they don't wake up. But running with GDB, everything works.
我禁用了所有优化。我尝试静态链接libstdc ++和libgcc,但没有任何效果。我尝试了一个小的测试程序,并且condition_variable正常工作。我还测试了Fedora 27,该问题得以解决。
I disabled all optimizations. I tried linking libstdc++ and libgcc statically, but nothing worked. I tried a small test program, and the condition_variable worked fine. I also tested Fedora 27, which fixed the problem.
这里是一个示例:
// worker thread
// term and cv passed in with std::ref()
std::atomic<bool> &_terminate = term;
std::condition_variable &_dataConditionVar = cv;
std::mutex acctMutex;
while (!_terminate.load(std::memory_order_relaxed)) {
// do stuff here ....
// wait for notification
std::unique_lock<std::mutex> acctLock(acctMutex);
_dataConditionVar.wait(acctLock); // Thread never wakes up <<
}
可以在Fedora 26/27上运行,但不能在Centos 7上运行。关于如何进行的任何建议?
Works on Fedora 26/27 but doesn't on Centos 7. Anyone have any advice on how to proceed?
推荐答案
如果在 _terminate之后设置了
,但在 _terminate
.load(std :: memory_order_relaxed) std :: unique_lock< std :: mutex>之前; acctLock(acctMutex);
, _dataConditionVar.wait(acctLock)
可能会永远阻止。
If _terminate
is set after _terminate.load(std::memory_order_relaxed)
but before std::unique_lock<std::mutex> acctLock(acctMutex);
, _dataConditionVar.wait(acctLock)
may block forever.
您不想将 std :: atomic
与 std :: mutex
和 std :: condition_variable
,因为这样的用法通常会导致这种竞争状态。通常,使用 std :: atomic
或 std :: mutex / std :: condition_variable
。
You do not want to use std::atomic
with std::mutex
and std::condition_variable
because such usage often leads to exactly this race condition. Normally, you use either std::atomic
or std::mutex/std::condition_variable
.
正确的用法是使 _terminate
普通 bool
并仅对其进行访问当持有互斥锁时:
The correct usage is to make _terminate
plain bool
and access it only when the mutex is held:
bool _terminate = false;
std::condition_variable _dataConditionVar;
std::mutex acctMutex;
// Set _terminate example.
{
std::unique_lock<std::mutex> acctLock(acctMutex);
_terminate = true;
_dataConditionVar.notify_one();
}
// Wait for _terminate to be set example.
{
std::unique_lock<std::mutex> acctLock(acctMutex);
while(!_terminate)
_dataConditionVar.wait(acctLock);
}
这篇关于std :: condition_variable仅在调试时有效吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!