多个与单个条件变量

时间:2018-05-29 09:18:12

标签: c++ multithreading condition-variable

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

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

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

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

1 个答案:

答案 0 :(得分:1)

我建议每个实际条件有一个condition_variable。例如,在生产者/消费者中,缓冲区为空的cv和缓冲区已满的另一个cv。

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

你问的是优化问题。一方面,我们希望避免过早优化,并在成为问题时进行分析。另一方面,我们希望设计的代码从一开始就能在算法上得到很好的扩展。

从速度性能的角度来看,在不了解情况的情况下很难说,但是添加cv的速度对速度产生显着负面影响的可能性非常低,与wait或{notify或{ {1}}。如果添加更多cv可以让你不再使用notify-all,那么对速度产生积极影响的可能性很高。

Notify-all用于简单易懂的代码。但是,当性能很重要时,不应该使用它。当一个等待cv的线程被唤醒时,它保证保持互斥锁。如果你通知所有,那么等待该cv的每个线程都会被唤醒并立即尝试获取互斥锁。此时,除了一个之外的所有人都会重新入睡(这一次等待互斥锁自由)。当幸运线程释放互斥锁时,下一个线程将获得它,接下来它将检查cv谓词。根据条件,谓词可能很可能评估为false(因为第一个线程已经处理了它,或者因为你有一个cv的多个实际条件)和线程立即回到睡觉等待简历。一个接一个,现在等待互斥锁的每个线程都会被唤醒,检查谓词,并可能回到cv上休眠。实际上只有一个人真的会做某事。

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

即使您调用notify-one,也可以考虑在关键部分之后执行此操作,以防止一个唤醒线程在互斥锁上阻塞。如果你真的想要通知所有,你可以简单地调用notify-one,并在完成关键部分后让每个线程通知一个。这创造了一个很好的线性级联转折与争用的爆发。