问题
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.
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.
Multiple worker threads go to sleep, but notification doesn't work, and they don't wake up. But running with GDB, everything works.
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.
Here is an example:
// 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 <<
}
Works on Fedora 26/27 but doesn't on Centos 7. Anyone have any advice on how to proceed?
回答1:
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.
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
.
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);
}
来源:https://stackoverflow.com/questions/50629479/stdcondition-variable-only-works-while-debugging