std :: condition_variable仅在调试时有效吗? [英] std::condition_variable only works while debugging?

查看:78
本文介绍了std :: condition_variable仅在调试时有效吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆