【问题标题】:Notify with confirmation in C++用 C++ 确认通知
【发布时间】:2019-01-16 15:06:39
【问题描述】:

我有一些并行运行的循环,并且有以下几行:

std::unique_lock <std::mutex> lock(_condLoopMutex);
_condLoopCondition.wait(lock, [this]() { return _conditionReady || _condLoopStopped; });
_conditionReady = false;

// DO SOMETHING

布尔变量

_conditionReady

通过以下构造设置在并行线程中:

_conditionReady = true;
_condLoopCondition.notify_one();

但是,有时我的程序会冻结。似乎通知来自函数“等待”传递参数并检查“_conditionReady”变量。

为避免这种情况,我实施了以下操作:

while (_conditionReady && !_condLoopStopped)
    {
        _condLoopCondition.notify_one();
        std::this_thread::sleep_for(std::chrono::microseconds(100));
    }

这样它会一直通知直到

_conditionReady == false

表示等待结束。

这是解决此问题的唯一方法 - 重新通知直到等待结束?有没有其他常规的方法来处理这些问题?

【问题讨论】:

  • 您应该在设置 _conditionReady 变量时持有互斥锁。此外,sleep从来没有解决方案。
  • 您也可以通过 std::atomic 进行同步。它可以大大简化你的代码。

标签: c++ parallel-processing stl


【解决方案1】:

首先,sleep 绝不是错误的解决方案。它确实应该在每次使用时生成一个编译器警告,这将传达相同的信息。

现在,每当您修改受条件保护的控制变量时,都应该在持有互斥体的同时完成 - 通常与 cond.wait() 中使用的相同。您的代码没有这样做。

【讨论】:

    【解决方案2】:

    当您修改 _conditionReady 变量时,您只需要保留互斥锁即可。这通过确保变量在检查其值和开始等待之间没有被修改来避免竞争条件。确保在调用 notify_one 之前或之后释放互斥锁以允许等待线程唤醒(如果在调用 notify 后执行此操作,则可以通过唤醒等待线程然后立即返回睡眠来引入小的性能损失当互斥锁被解锁时,互斥锁在第二次唤醒之前被锁定)。例如:

    {
      std::unique_lock <std::mutex> lock(_condLoopMutex);
      _conditionReady = true;
    }
    _condLoopCondition.notify_one();
    

    【讨论】:

    • 感谢您的详细解答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    • 1970-01-01
    • 2015-06-10
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多