等待线程的最佳方式是什么

What is the best way to wait a thread?

本文关键字:方式 是什么 最佳 线程 等待      更新时间:2023-10-16

有时会出现这样的情况,即线程需要等待,直到它从另一个线程获得信号。目前我通过以下方式实现这一点:(有一个volatile int signal;由另一个线程设置,用于告诉等待的线程继续(

方法1:本能地最低延迟,但等待时最高cpu使用率:

while(signal != 1);

方法2:仍然使用100%cpu/core,但我认为更善于给其他线程一个运行的机会?仍然非常低延迟的

while(signal != 1) Sleep(0);

方法3:等待时cpu使用率可以忽略不计(在任务管理器中报告为0%(,但显然有1ms的延迟。

while(signal != 1) Sleep(1);

有更好的方法来处理这个案子吗?主要对本机c++Win32感兴趣,但也对linux/android/ios感兴趣。

如果没有神奇的低延迟/低等待cpu使用率解决方案,我对以下两种情况下的最低延迟解决方案都感兴趣:等待cpu使用量无关紧要,等待cpu使用应该可以忽略不计。

如果这是一个小问题,我很抱歉,但我对这种事情还不熟悉。

;右";这里的答案取决于您对延迟和吞吐量的重视程度——也就是说,这个特定线程在发出信号后尽快开始处理更重要,还是其他线程在等待时获得最大的CPU时间更重要?在很多情况下,所需的内容还取决于线程在准备好继续之前等待的时间。

现在,您正在进行繁忙的等待——也就是说,在等待期间,您在一定程度上保持CPU(至少有一个核心(繁忙,检查它是否可以继续。

执行Sleep(0)基本上将当前线程放在准备执行并等待CPU执行的线程队列的后面。因此,如果没有其他线程在等待,它仍然会消耗100%的CPU。另一方面,如果具有相同优先级的其他线程已准备好运行,则它们将有机会在再次调度此线程之前运行。

不过有一点:volatile并没有像这样真正为线程间通信定义,所以您希望使用原子变量。

std::atomic<bool> signal { false };
while (!signal)
Sleep(0); // or Sleep(1)

如果在signal变成true之前只需要几毫秒(或按这个顺序(,那么线程就可以继续了。由于它等待的时间不长,因此在等待期间不会占用大量CPU时间,而且(尤其是在系统负载较轻的情况下(当signal变为true时,它可以非常快速地做出响应。

如果线程等待的时间可能超过几毫秒,那么您最好使用一些机制来获取当前线程并将其标记为未准备好运行,而是在某个内核对象上等待,然后才能/将其再次调度。Windows为此提供Event

HANDLE signal = CreateEvent(/* ... */);
WaitForSingleObject(signal, INFINITE);

当其他代码想要发出这个线程应该运行的信号时,它会执行如下操作:

SetEvent(signal);

对于这种简单的情况,Windows事件可能工作得很好,但在复杂的情况下,获得你想要的东西可能会在困难和完全不可能之间徘徊(尽管大多数情况下变得困难是因为你可能应该使用事件以外的东西(。

您也可以使用标准库中的条件变量,但它有点复杂。条件变量总是与互斥对象以及您关心的条件一起使用。所以在你的案例中使用它会看起来有点像这样:

std::atomic<bool> signal;
std::mutex m;
std::condition_variable v;
std::unique_lock<std::mutex> lock(m);
v.wait(lock, [&] { return signal; });

如果其他代码发出信号表示这个线程可以运行,它会执行以下操作:

std::unique_lock<std::mutex> lock(m);
signal = true;
v.notify_one();

条件变量确实有优点,但无论如何,它都不是最简单的使用方法。另一方面,一旦你习惯了所涉及的样板,这也不是特别困难。