忙等待和轮询有什么区别?

16

来自维基百科关于轮询的文章:

在计算机科学中,轮询或称多路复用(英文:Polling),是指客户端程序主动地对外设状态进行采样的同步活动。轮询通常在输入输出(I/O)方面使用,也被称为轮询 I/O 或软件驱动 I/O。

轮询有时与繁忙等待轮询(busy-wait polling)作为同义词使用。在这种情况下,当需要进行 I/O 操作时,计算机除了检查 I/O 设备的状态以外,什么都不干,直到设备准备就绪才访问该设备。换句话说,计算机一直等到设备准备就绪。
轮询还指设备反复检查是否准备好,如果设备没有准备好,计算机会返回到其他任务上。虽然与繁忙等待相比不浪费 CPU 循环,但通常不如轮询的替代方法——中断驱动 I/O 效率高。

那么,当线程不使用“条件变量”时,它是被称为数据更改的“轮询”还是“繁忙等待”?


相关:轮询还是等待更好? - Piotr Dobrogost
2个回答

36

这两者之间的区别在于程序在轮询之间执行的操作。

如果一个程序每秒轮询一次设备,并且在没有可用数据时做其他事情(包括可能只是休眠,让 CPU 可用于其他任务),那就是轮询。
如果程序在连续检查设备(或资源或其他内容)之间不做任何操作,那就称为忙等待。

这与同步无直接关系。一个在条件变量上阻塞(当一个设备或资源可用时应该通知它)的程序既不是轮询也不是忙等待。这更像是事件驱动/中断驱动的 I/O。
(但是,例如一个循环使用 try_lock 的线程是一种轮询形式,如果循环很紧密,可能是忙等待。)


将busy-wait定义为应用程序除调用低级别(操作系统?)轮询函数以等待事件之外的任何操作(包括任何紧密的for循环)是否更加精确? - Piotr Dobrogost

10

假设有一个微处理器或微控制器,当它注意到按钮被按下时,它应该执行某些操作。

第一种方法是使程序进入一个循环,在此循环中除查看按钮是否已更改外不进行任何操作,一旦更改,即执行所需操作。

在某些情况下,第二种方法是编程硬件,在按钮被按下时触发中断,假设按钮连接到可以引起中断的输入。

第三种方法是配置定时器以在某个速率(例如1000次/秒)中断处理器,并使该中断的处理程序检查按钮的状态并根据其进行操作。

第一种方法使用忙等待。 它可以为一个特定的刺激提供非常好的响应时间,但代价是完全屏蔽其他所有事情。 第二种方法使用事件触发中断。 它通常会比忙等待稍微慢一点,但会允许CPU在等待I/O时执行其他任务。 它还可以使CPU进入低功耗睡眠模式,直到按下按钮。 第三种方法将提供远远低于其他两种方法的响应时间,但即使硬件不允许通过按下按钮触发中断,它仍可用。

在需要快速响应的情况下,通常需要使用事件触发中断或忙等待。 但在许多情况下,轮询方法可能最实用。 硬件可能不存在以支持所有感兴趣的事件,或者感兴趣的事件数量可能大大超过可用的中断数量。 此外,可能希望某些条件生成延迟响应。 例如,假设希望计算开关被激活的次数,符合以下标准:

  1. 每个合法的开关事件将包括一个从0到900微秒(μs)的间隔,在该间隔内,开关可以任意关闭和重新打开,随后至少1.1毫秒的间隔内,开关将保持关闭状态,之后是一个从0到900微秒的间隔,在该间隔内,开关可以任意打开和重新关闭,最后是至少1.1毫秒的间隔,在此期间,开关将保持开启状态。
  2. 在任何未被忽略的开关打开或关闭之后的950微秒内,软件必须忽略开关的状态。
  3. 软件可以任意计数或忽略在上述所需空白间隔之外发生的持续时间小于1.1毫秒的开关事件。
  4. 软件报告的计数必须在开关稳定"关闭"的时间内有效,时间限制为1.99毫秒。

    最简单的实现要求的方法是以1,000次/秒的频率观察开关的状态;如果看到上一个状态为“打开”的状态下它被视为“关闭”,则将计数器增加。非常简单易懂;即使开关以各种奇怪的方式打开和关闭,在真实事件的前后900us内,软件也不会在意。

    虽然满足所需的空白要求,但是可以使用开关输入触发中断以及定时器来提高对开关输入的响应速度。最初,输入将被设置为在下次开关关闭时触发。一旦触发中断,软件将禁用它,但设置一个定时器,在950微秒后触发中断。一旦该计时器到期,它将触发一个中断,该中断将使中断在下次开关“打开”时触发。然后,该中断将禁用开关中断,并再次设置950微秒的计时器,以便定时器中断再次启用开关中断。有时这种方法可能很有用,但是与简单轮询方法相比,软件要复杂得多。当基于定时器的方法足够时,通常更可取。

    在使用多任务操作系统而非直接中断的系统中,许多相同的原则适用。与等待某些事件发生后才运行操作系统的代码相比,定期进行I/O轮询会浪费一些CPU时间,但在许多情况下,事件响应时间和没有事件发生时浪费的时间都是可以接受的。实际上,在某些缓冲I/O情况下,周期性轮询可能会很有效。例如,假设通过串口从远程机器接收大量数据,每秒最多会到达11,520字节,设备将发送不超过2K的数据以前的最后确认数据包,并且串口具有4K输入缓冲区。虽然可以使用“数据接收”事件处理数据,但只需100次/秒检查端口并处理接收到的所有数据包可能同样有效。当远程设备未发送数据时,这种轮询将是浪费时间的,但如果预期有传入数据,则以大约1.15K的块处理数据可能比即时处理每个小块传入数据更有效率。


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