我在C ++ 14中编写了一个项目,在Fedora 26上使用Intel的icpc编译(gcc 7依赖)。一切都很好并且正常工作,直到我将我的项目移到Centos 7上,并开始体验非常神秘的行为。
On Centos(scl enable devtoolset-7 bash),源代码编译和链接没有错误,但该项目仅在使用GDB进行调试时有效。没有调试,条件变量唤醒睡眠线程的通知就不起作用。
多个工作线程进入睡眠状态,但通知不起作用,并且它们不会被唤醒。但是使用GDB运行,一切正常。
我禁用了所有优化。我尝试静态链接libstdc ++和libgcc,但没有任何效果。我尝试了一个小测试程序,condition_variable运行正常。我还测试了Fedora 27,它解决了这个问题。
以下是一个例子:
// 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上。任何人都有关于如何进行的任何建议吗?
答案 0 :(得分:1)
如果_terminate
在_terminate.load(std::memory_order_relaxed)
之后但在std::unique_lock<std::mutex> acctLock(acctMutex);
之前设置,则_dataConditionVar.wait(acctLock)
可能会永久阻止。
您不希望std::atomic
与std::mutex
和std::condition_variable
一起使用,因为这种使用通常会导致这种竞争条件。通常,您使用std::atomic
或std::mutex/std::condition_variable
。
正确的用法是_terminate
普通bool
并仅在持有互斥锁时访问它:
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);
}