等待条件变量会占用CPU核心吗?

5

等待条件变量会导致循环以指令的形式将CPU核心负载到100%吗? 在C++中,等待cvar通常是这样完成的:

void worker_thread()
{
    // Wait until ready turns true and the condition variable is notified
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, []{return ready;}); //<-- does this load the cpu?
    // Do something
}

我假设类似这样的实现是其基础:
while (1)
{
    lock mutex;
    if (condition) signal();
    unlock mutex;
}

这段代码会使当前处理器核心的负载达到100%,因为没有使用Sleep()函数进行休眠。
实际情况会怎样呢?

1
不是的,它不会持续轮询以检查信号状态,而是等待状态被通知。这是一种通过信号来同步线程的相当有效的方式。 - seccpur
1
我想这取决于具体的实现,因为C++标准并没有规定线程需要从CPU中移除。 - AndyG
在任何合理的实现中,wait()调用将与线程调度程序协作实现;即调用线程将被置于休眠状态,直到条件变量被发信号为止;当信号发生时,线程调度程序将再次唤醒线程,以便wait()可以返回。在线程处于睡眠状态时不会使用额外的CPU周期。 - Jeremy Friesner
4个回答

2
在我的情况下(这就是我找到你的问题的方式),问题在于没有为编译器和链接器指定-pthread。是的,没有那个标志一切都可以编译和链接,但会导致CPU使用率达到100%。

1
在我使用的任何编译器和操作系统中,它都不会发生。通常,同步原语的底层操作是作为内核调用执行的,除非显式声明,并且操作系统的内核负责如何执行。即使它不在标准中,我认为它只是为了允许遵循C++标准的编译器存在于异构体系结构上。除非你正在使用非常罕见和特定的东西,否则你不应该关心它。

1
一般来说,这个逻辑围绕操作系统中的调度器实现。等待和唤醒线程的功能与操作系统的调度器配合完成。
通用/简单设计: 在上述情况下,等待将导致线程休眠,因此调度程序将把线程从运行状态(运行队列)移动到等待/阻塞状态(等待队列),除非满足特定条件。因此,在这种情况下,通常不会消耗CPU周期。
一旦满足条件,信号量将通知调度程序,以便调度程序可以唤醒等待条件的线程并对其进行调度(即,它将把线程从等待/阻塞状态(等待队列)移动到运行状态(运行队列)并对其进行调度)。

0
在我的情况下,我已经对我的应用进行了分析,似乎它在等待时消耗了大量的CPU,仅在等待时占用了30%的CPU。这是很多CPU,因为我运行的应用是一个拥有1000个繁重绘制调用和粒子系统计算的完整游戏。在我的情况下,等待发生在iOS上的__psynch_cvwait。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接