与std :: condition_variable_any相关的开销是多少

时间:2017-10-07 08:29:04

标签: c++ multithreading c++11 mutex condition-variable

我在许多地方都读过,std::condition_variable_any会产生一些开销。只是想知道,这是什么开销?

我的猜测是因为这是一个可以与任何类型的锁一起使用的通用条件变量,它需要手动滚动的等待实现(可能还有另一个condition_variable和互斥或futex,或类似的东西)所以额外的开销可能来自那个?但不确定......而不是仅仅是pthread_cond_wait()的本地包装(以及其他系统上的等价物)等。

作为后续,如果我说实现等待的东西,比如说,共享的互斥锁,那么这种类型的条件变量是不是因为性能开销的选择?在这种情况下我还能做些什么?

1 个答案:

答案 0 :(得分:3)

pthread_cond_wait() / SleepConditionVariableSRW(),与普通std::condition_variable::wait()相同,只需要一个原子系统调用来释放互斥锁,等待条件变量并重新获取互斥锁。线程立即进入休眠状态,另一个线程 - 理想情况是被互斥锁阻塞的线程 - 可以立即在同一个核心上接管。

使用std::condition_variable_any,解除传递的BasicLockable并开始等待本机事件/条件不仅仅是一个系统调用,而是调用unlock()方法{ {1}}首先,然后才发出系统调用以进行等待。所以你至少得到了单独的BasicLockable的开销,而且你更有可能在OS端触发一个不太理想的调度决策。最糟糕的情况是,解锁甚至导致在不同核心上继续等待线程,并带来所有相关的开销。

相反,例如,在虚假唤醒时,在处理不适用于通用unlock()的本机互斥(在std::mutex中使用)时,也可以进行操作系统端调度优化。

两者都涉及一些簿记,以便提供BasicLockable逻辑(它实际上是每个等待线程的一个事件/条件)以及所有方法都是原子的保证,所以它们都带来了一个小的开销

真正的开销来自OS如何在组合的信号和等待锁定系统调用上做出良好的调度决策。如果操作系统不熟悉调度,那么它几乎没有区别。