【问题标题】:Multiple vs single condition variable多个与单个条件变量
【发布时间】:2018-05-29 09:18:11
【问题描述】:

我正在开发一个应用程序,目前我只有一个条件变量和许多不同条件的等待语句。每当其中一个队列或其他状态发生更改时,我只需调用 cv.notify_all(); 并知道所有等待此状态更改的线程都会收到通知(可能还有其他正在等待不同条件的线程)。

我想知道为每个队列或状态使用单独的条件变量是否有意义。我所有的队列通常都是独立的,因此等待队列x 中的数据的线程并不关心队列y 中的新数据。所以我不会遇到必须通知或等待多个条件变量的情况(这是我发现的大多数问题)。

从性能的角度来看,周围有几十个条件变量有什么缺点吗?当然,代码可能更容易出错,因为必须通知正确的条件变量。

编辑:所有条件变量仍将使用相同的互斥锁。

【问题讨论】:

  • 拥有多个条件变量的问题是如果/当您需要等待多个条件变量时,没有好的方法可以做到,如果您不需要等待多个条件变量它最好有多个,因为这样会减少无用的通知
  • @MikhailVasilyev 所有条件变量都将使用相同的互斥锁,所以我相信我的问题与链接的问题不同。
  • 如果您只想通知某些线程是有意义的,只有与特定特定 cv 关联的线程才会被通知。
  • 我使用单个条件变量来处理多次等待,结果非常可接受。我使用 atomic int 作为“地址”来识别等待和通知。只有“地址”与通知地址匹配的等待才会响应通知。我把所有繁琐的东西都包在了一个类中,用法基本是 foo.wait(my_address); 和 foo.notify(some_address);许多不同的线程可能正在等待,我什至处理了多个线程在同一个地址上等待的情况,这是我的应用程序中的常见情况。

标签: c++ multithreading condition-variable


【解决方案1】:

我建议每个实际条件有一个condition_variable。例如,在生产者/消费者中,buffer empty 会有一个 cv,buffer full 会有另一个 cv。

当你可以只通知一个时通知所有人是没有意义的。这让我觉得您的 condition_variable 实际上管理着几个实际条件。

您是在询问优化。一方面,我们希望避免过早优化并在问题出现时进行分析。另一方面,我们希望设计的代码从一开始就可以在算法上很好地扩展。

从速度性能的角度来看,在不了解情况的情况下很难说,但是添加 cv 对速度产生重大负面影响的可能性非常低,与waitnotify 的成本相比完全相形见绌.如果添加更多 cv 可以让您不再调用 notify-all,那么对速度产生积极影响的可能性就很高。

Notify-all 使代码易于理解。但是,当性能很重要时,不应使用它。当一个等待 cv 的线程被唤醒时,它保证持有互斥锁。如果您全部通知,则等待该 cv 的每个线程都将被唤醒并立即尝试获取互斥锁。到那时,除了一个之外,其他所有人都将重新进入睡眠状态(这次等待互斥体空闲)。当幸运线程释放互斥锁时,下一个线程将得到它,接下来要做的就是检查 cv 谓词。根据条件,谓词很可能评估为 false(因为第一个线程已经处理了它,或者因为您有多个 actual 一个 cv 条件)并且线程立即回去睡觉等待简历。一个接一个,现在等待互斥锁的每个线程都会唤醒,检查谓词,并可能在 cv 上重新进入睡眠状态。很可能只有一个人最终会做某事。

这是可怕的性能,因为互斥锁、互斥解锁、cv 等待和 cv 信号都相对昂贵。

即使您调用 notify-one,您也可能会考虑在临界区之后执行此操作,以尝试防止唤醒的线程阻塞互斥体。如果你真的想全部通知,你可以简单地调用 notify-one 并让每个线程在完成关键部分后通知一个。这创造了一个很好的线性级联轮流与争用的爆发。

【讨论】:

    猜你喜欢
    • 2019-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多