当前位置: 首页 > 知识库问答 >
问题:

如果我执行线程.sleep(),等待真的很忙吗?

柳宏深
2023-03-14

我的问题在定义上有点挑剔:

下面的代码可以用“忙着等待”来形容吗?尽管它使用thread.sleep()来允许上下文切换?

while (true) {
    if (work_is_ready){
        doWork();
    }
    Thread.Sleep(A_FEW_MILLISECONDS);
}

PS--维基百科目前对忙碌等待的定义表明,忙碌等待是一种“不太浪费”的形式。

共有2个答案

秦炜
2023-03-14

那不是忙着等。忙着等待,或者旋转,涉及到相反的问题:避免上下文切换。

如果您希望允许其他线程运行,当且仅当其他线程准备好运行,以避免单线程CPU中的死锁场景(例如,当前线程需要work_is_ready设置为true,但如果此线程不放弃处理器而让其他人运行,则永远不会设置为true),则可以使用thread.sleep(0)

更好的选择是使用spinwait.spinuntil

SpinWait.SpinUntil(() => work_is_ready);
doWork();

spinwait发出一个特殊的代表;nop(重复no-op)或pause指令,它让处理器知道您正在等待,并针对超线程CPU进行了优化。此外,在单核CPU中,这将立即产生处理器(因为如果只有一个核,繁忙的等待是完全没有用的)。

但是,只有当您绝对确定您等待条件的时间不会超过处理器将上下文切换出来和再切换回来所需的时间时,旋转才是有用的。即不超过几微秒。

如果您希望每隔几毫秒轮询一个条件,那么您应该使用一个阻塞同步原语,正如wiki页面所建议的那样。对于您的场景,我建议使用AutoResetEvent,它在调用Waitone时阻止线程,直到事件发出信号(即条件变为true)。

另请阅读:同步原语概述

锺离逸春
2023-03-14

任何轮询循环,无论轮询操作之间的时间长短,都是忙等待。当然,睡眠几毫秒比完全不睡眠要少得多,但它仍然涉及处理:线程上下文切换和一些最小条件检查。

非忙等待是阻塞呼叫。您的示例的非繁忙版本将涉及等待同步原语,如事件或条件变量。例如,这个伪代码:

// initialize an event to be set when work is ready
Event word_is_ready;
work_is_ready.Reset();

// in code that processes work items
while (true)
{
    work_is_ready.Wait();  // non-busy wait for work item
    do_work();
}

这里的区别是没有定期轮询。wait调用将阻塞,并且在事件设置之前永远不会调度线程。

 类似资料:
  • 嗨,我正在做一个项目,我已经达到了我非常困的部分。我试图寻找方法来学习如何在繁忙的等待中编写 while 循环,但我没有找到任何东西,我的代码只是作为无限循环运行。有人可以帮助我解释一个繁忙的等待循环应该如何工作,并帮助我打破这个无限循环吗? 该项目希望做到以下几点:早上,学生醒来后(这需要一段随机的时间),他会去洗手间为新的上学日做准备。如果浴室已经客满,学生需要Rest一下(使用yield()

  • 问题内容: 我有执行子进程的程序 运行此命令时,它会下载并安装npm软件包,这需要花费10到40秒的时间,并且用户直到看到标准输出(10-40秒取决于网络)才知道发生了什么,我可以做一些事情使用哪个可以在cli上打印一些东西,以便更清楚地说明发生了什么事情,一些忙碌的指示器(任何类型),直到将stdout打印到cli上? 问题答案: 您可以使用另一个goroutine定期(例如每秒)打印一些内容(

  • 问题内容: 我正在为我的ubuntu服务器(针对我的多客户端匿名聊天程序)实现一种简单的线程池机制,并且需要使我的工作线程进入睡眠状态,直到需要执行一项工作(以函数指针和参数的形式) 。 我当前的系统即将关闭。我(工人线程正在)问经理是否有工作可用,以及是否有5毫秒没有睡眠。如果存在,请将作业添加到工作队列中并运行该函数。糟糕的循环浪费。 什么我 喜欢 做的是做一个简单的事件性的系统。我正在考虑有

  • 我正在编写一个简单的代码,用javaFX显示表的内容。我希望程序在每次显示新内容时暂停。 问题是,无法按计划工作。事实上,程序甚至在显示内容之前都会暂停。 我如何纠正这个问题?

  • 问题内容: 我是python的n00b用户,并且正在查找执行以下操作的代码段/示例: 显示类似“按任意键进行配置或等待X秒继续”的消息 例如,等待5秒钟,然后继续执行,或者如果按下某个键,则输入configure()子例程。 感谢您的帮助! 伊万·詹森斯(Yvan Janssens) 问题答案: 如果您使用的是Unix / Linux,那么select模块将为您提供帮助。 如果您使用的是Windo

  • 问题内容: 在这里,我想每秒钟调用一次“ Log.d”和“ postInvalidate”。但是,当我从LogCat检查它时,似乎循环运行的速度比我希望的要快。为什么这个循环不等待1000ms? 以下是LogCat中的输出。因此,您可以看到它根本没有休眠1秒钟。我也使用了Thread.sleep(在您建议之后) 这是最新的代码。是布尔值,现在是事实。 输出是 问题答案: 您需要类的方法。 使发送此