【问题标题】:notify_one performance impactnotify_one 性能影响
【发布时间】:2016-05-17 20:46:34
【问题描述】:

我正在阅读一些关于 std::condition_variable 的内容,尤其是关于如何使用 std::condition_variable::notify_one 通知等待线程的内容。

我遇到了几个问题,我很乐意得到答案:

  • 当一个线程调用notify_one(操作系统方面)时究竟会发生什么?我想这是特定于操作系统的,所以为了争论 - 我在 Windows 中工作。
  • 如果一个线程在没有等待线程的情况下调用notify_one,会发生什么?此调用是否会对性能产生任何影响(CPU 周期、电源等)?

谢谢

【问题讨论】:

    标签: c++ windows multithreading c++11


    【解决方案1】:

    在 Windows 上,std::condition_variable 很可能根据本机 Windows 条件变量来实现。 见:https://msdn.microsoft.com/en-us/library/windows/desktop/ms682052(v=vs.85).aspx

    在类 unix 系统上,它们通常以 pthreads 信号量/互斥量对的形式实现。

    整个操作应该在用户空间中进行,因此您无需付费切换到内核模式,但您将在幕后使用两个同步原语。这意味着内存栅栏将被发布,因此总是要付出一些代价。

    长话短说,当你应该调用notify_one,即在改变条件状态并释放锁之后,这是一个相当便宜的操作。无缘无故地循环调用notify_one 可能不是一个好主意。

    如果一个线程在没有等待线程的情况下调用 notify_one 会发生什么?

    取一个互斥体,检查是否有线程在等待,释放互斥体。结束。

    此调用是否会对性能产生任何影响(CPU 周期、电源等)?

    是的,当然,它会消耗几个周期,并且需要 CPU 正在运行。偶尔做一次不会有伤害的。在紧密的循环中连续执行会消耗功率。

    我想我的问题是,“用例是什么”?如果您每秒向生产者/消费者队列添加一百万个项目,那么您将花费大量时间和精力来通知不存在的消费者。如果您每秒增加 10 个,那么在 notify_one 上花费的时间可能甚至不会显示在任何性能跟踪中。

    【讨论】:

    • 在 unix 系统上,如果涉及互斥锁,整个通知操作如何避免切换到内核模式?我想这实际上取决于互斥锁本身的实现。
    • @athos 你的意思是unix还是Linux?据我了解,linux 提供了 futex,它是一个用户空间对象。我不相信涉及到任何切换到内核模式。
    • 我是说unix,比如mac os...有futexes吗?
    【解决方案2】:

    这些问题是非常特定于实现的。仅仅说你在 Windows 上是不够的。每个标准库可能有不同的实现,调试版本可能与发布版本有不同的实现。

    notify_one 在没有线程等待时的语义效果是无操作。在实现方面,至少线程必须检查一个原子变量以确定是否有任何线程在等待。所以有一点开销。

    Microsoft 标准库的 condition_variable 是根据并发运行时的条件变量实现的,从 Windows Vista 开始,它是根据 WinAPI RTL_CONDITION_VARIABLE 实现的。它的实现是不可访问的。但是,它的实现很有可能是基于这篇 Microsoft 研究论文:

    http://research.microsoft.com/pubs/64242/implementingcvs.pdf

    【讨论】:

      猜你喜欢
      • 2015-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-30
      • 2021-03-09
      相关资源
      最近更新 更多