std :: condition_variable仅在调试时有效吗?

时间:2018-05-31 17:09:14

标签: c++ centos gdb condition-variable

我在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上。任何人都有关于如何进行的任何建议吗?

1 个答案:

答案 0 :(得分:1)

如果_terminate_terminate.load(std::memory_order_relaxed)之后但在std::unique_lock<std::mutex> acctLock(acctMutex);之前设置,则_dataConditionVar.wait(acctLock)可能会永久阻止。

您不希望std::atomicstd::mutexstd::condition_variable一起使用,因为这种使用通常会导致这种竞争条件。通常,您使用std::atomicstd::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);
}