等待条件的空循环(忙等待)
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));
【讨论】:
以上是关于等待条件的空循环(忙等待)的主要内容,如果未能解决你的问题,请参考以下文章