等待条件的空循环(忙等待)

Posted

技术标签:

【中文标题】等待条件的空循环(忙等待)【英文标题】:Empty loop which waits for condition (busy-waiting) 【发布时间】:2015-03-13 11:31:16 【问题描述】:

过去 20 分钟我一直在研究空循环,其目的只是等待条件变为真。

我有一个名为“waitForLoaded”的函数,它是由 CreateThread 创建的线程。

功能:

void waitForLoaded()
    while(!isLoaded)
        Sleep(500); // < my question
    
    Sleep(500); //sleep another 500ms to ensure everything is loaded.
    //continue on here

我使用 Sleep(500) 来简化 CPU,因为我相信使用 0 或 1 会耗尽处理器。

我在很多人中看到过使用“Sleep(0)”的代码,但我一直不明白为什么不只是不睡觉,而是执行“while(condition)..”

我找不到任何可靠的答案来说明哪个对 CPU 更友好,所以我在这里问人们,忙等待与 0 毫秒、1 毫秒或 500 毫秒有什么区别,哪个对 CPU 更友好。

在我看来,最好至少睡半场,这几乎不会被用户注意到。

【问题讨论】:

“你个人会做什么”是一个基于意见的问题,这并不是这个网站的真正用途。 @DrewDormann 你是绝对正确的,我应该问为什么一个比另一个更好。我会改变我的问题。 sleep(0) 至少会导致线程重新调度。它不等同于“根本不睡觉”。睡多久取决于你。代码中的最后休眠是没有意义的。 如果你的应用是单线程的,调用 waitForLoaded 将永远冻结你的应用! @Maher 当然它不是单线程的,如果应用程序冻结,我就不会在这里问同样的问题。感谢您的意见。 【参考方案1】:

在 Windows 上,Sleep(0) 不会花费任何时间休眠,但允许操作系统将 CPU 让给另一个等待线程。这有点像说“如果有人在排队,让他们先去吧,否则我想马上去。”

【讨论】:

很好的答案,它完全可以理解并且非常有帮助。谢谢你回答我的问题。我从来都不太确定“线程重新调度”是什么意思。【参考方案2】:

如果我理解您的问题,那么您是在问这些等待方法中哪个更好:

sleep(500) sleep(1) sleep(0) // (do nothing)

如果你有时间买一个sleep(500),那么答案是“sleep(500)

【讨论】:

我也喜欢你的回答,在我看来,让 CPU 休息的时间越长越好。我需要更好地理解“线程重新调度”,这样我才能完全理解其他人所说的使用 Sleep(0) 的好处。谢谢。【参考方案3】:

围绕事件或类似事物的简单同步原语将消耗更少的 CPU,并且您的线程有望在 500 毫秒等待的最坏情况下比 500 毫秒更快地开始工作。

【讨论】:

我之前遇到过“同步原语”,但从未深入了解它的含义。我会做我的研究,谢谢。【参考方案4】:

首先你需要研究你的问题。

您需要忙碌的等待吗? 您可以使用调度程序吗? 您能否检测到数据可用或操作完成的确切时刻?

我会研究不同的方法,例如事件文件描述符或条件变量。

条件变量法:

boost::mutex::scoped_lock lock(m_mutex);
while(queue.empty() && !m_quit) 
    m_condition.wait(lock);
    

事件文件描述符方法

m_loopFD = eventfd(0,EFD_CLOEXEC|EFD_NONBLOCK);
if(m_loopFD < 0) 
    close(m_epollFD);
    throw ...

struct epoll_event event;
memset(&event, 0, sizeof(struct epoll_event));
event.data.fd = m_loopFD;
event.events = EPOLLIN;
if(epoll_ctl(m_epollFD, EPOLL_CTL_ADD, m_loopFD, &event) != 0) 
    throw ...

以后你可能会有这样的事情

int res = epoll_wait(m_epollFD, events, MAX_EVENTS, timeout);

然后唤醒它:

uint64_t value = 0x01;
write(m_loopFD, &value, sizeof(value));

【讨论】:

以上是关于等待条件的空循环(忙等待)的主要内容,如果未能解决你的问题,请参考以下文章

如何处理:循环调用'Thread.sleep()',可能是忙等待

函数在继续循环之前不等待条件完成

等待没有循环Python的条件

防止 MPI 忙循环

实战并发编程 - 07循环等待&死锁问题

javascript:循环中如何等待方法完成了再继续?