【问题标题】:why is std::condition_variable::notify_one blocking?为什么 std::condition_variable::notify_one 阻塞?
【发布时间】:2016-05-09 04:32:34
【问题描述】:

由于某种原因,调用 signal.notify_one() 会阻塞当前线程并且不会返回。我从未听说过这种行为,也不知道如何解决。

{
  std::lock_guard<std::mutex> lock(_mutex);
  _exit = true; // _exit is a std::atomic<bool> 
}

std::cout << "before" << std::endl;
_signal.notify_one();
std::cout << "after" << std::endl;

_thread.join();

我使用的是 Microsoft Visual C++ 2015,上面的代码在销毁过程中被调用。

希望你能给我指明正确的方向,非常感谢你的帮助!

【问题讨论】:

  • 上面的sn-p代码是不是来自回调?您可以包含正在等待通知的代码吗?还有一点,你不需要_exitstd::atomic,因为它受到_mutex 的保护。
  • notify_one 的调用可能会唤醒一个已调用_signal.wait() 的线程,这可能是您的代码所在的位置。考虑在您的_signal.wait() 之后添加断点以查看您的代码是否返回到该位置

标签: c++ multithreading visual-studio-2015 poco-libraries condition-variable


【解决方案1】:

好吧,我终于找到了问题所在。为了提供一些背景知识,我目前正在使用一些 Poco 库(请参阅 http://pocoproject.org/)并且我实现了自己的 Poco::Channel。经过一番挖掘,我意识到 Poco 将所有通道保存在 static LoggingRegistry 中,只有在所有剩余线程都被杀死后才会释放。

我最好的猜测是,如果一个正在等待 std::condition_variable 的线程被杀死,那么 std::condition_variable 就会变得无效。

无论如何,为了防止出现问题,必须在main(int argc, char** argv) 返回之前调用以下代码:

Poco::Logger::shutdown();
Poco::LoggingRegistry::defaultRegistry().clear(); 

【讨论】:

  • 感谢您发布您的发现。编辑问题标题和标签以帮助其他 Poco 用户(以及更少的非 Poco 用户)找到问题可能会很好......
  • 我认为这个答案是为什么过度简化你的问题到缺少所有相关细节的地步是不好的。
【解决方案2】:

我在嵌入式环境中遇到了类似的行为。根据您的操作系统中条件变量的实现方式,通知线程可能会隐式等待通知线程。

如果您的通知线程具有非常低的优先级并且被阻止运行一段时间,对 notify_one() 的调用也可能会被阻止,直到系统有时间安排低优先级任务。

【讨论】:

    猜你喜欢
    • 2012-02-19
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多