std::condition_variable 只在调试时有效?
std::condition_variable only works while debugging?
我用 C++14 写了一个项目,在 Fedora 26 上用 Intel 的 icpc 编译(依赖 gcc 7)。一切都很好并且工作正常,直到我将我的项目转移到 Centos 7 上,并开始遇到非常神秘的行为。
在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。有人对如何进行有任何建议吗?
如果_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);
}
我用 C++14 写了一个项目,在 Fedora 26 上用 Intel 的 icpc 编译(依赖 gcc 7)。一切都很好并且工作正常,直到我将我的项目转移到 Centos 7 上,并开始遇到非常神秘的行为。
在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。有人对如何进行有任何建议吗?
如果_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);
}