【问题标题】:What is the difference between busy-wait and polling?忙等待和轮询有什么区别?
【发布时间】:2012-05-22 14:13:00
【问题描述】:

来自Polling 上的维基百科文章

计算机科学中的轮询或轮询操作是指客户端程序主动采样外部设备的状态作为同步活动。轮询最常用于输入/输出 (I/O),也称为轮询 I/O 或软件驱动 I/O。

轮询有时与忙等待轮询(忙等待)同义使用。在这种情况下,当需要 I/O 操作时,计算机只会检查 I/O 设备的状态,直到它准备好,此时设备被访问。换句话说,计算机会一直等到设备准备好。
轮询还指反复检查设备是否准备就绪,如果不是,则计算机返回其他任务的情况。虽然不像忙等待那样浪费 CPU 周期,但它通常不如轮询、中断驱动 I/O 的替代方案那么有效。

那么,当一个线程不使用“条件变量”时,是否会因为数据变化而被称为“轮询”或“忙于等待”呢?

【问题讨论】:

标签: multithreading polling condition-variable busy-waiting


【解决方案1】:

两者的区别在于应用程序在轮询之间所做的事情。

如果一个程序每秒轮询一个设备,并且在没有数据可用的情况下同时执行其他操作(包括可能只是休眠,让 CPU 可供其他人使用),它就是轮询。
如果程序在两次检查之间连续轮询设备(或资源或其他)而不做任何事情,则称为忙等待。

这与同步没有直接关系。阻塞条件变量(应在设备或资源可用时发出信号)的程序既不是轮询也不是忙等待。这更像是事件驱动/中断驱动的 I/O。
(但例如,围绕try_lock 循环的线程是一种轮询形式,如果循环紧张,可能会忙于等待。)

【讨论】:

  • 不会将忙等待定义为应用程序执行任何操作但调用较低级别(OS?)轮询函数以等待事件(包括任何 for 循环,无论多紧)的情况准确吗?
【解决方案2】:

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

第一种方法是让程序进入一个循环,该循环什么都不做,只是查看按钮是否已经改变,一旦改变,就执行所需的操作。

在某些情况下,第二种方法是对硬件进行编程,以在按下按钮时触发中断,假设按钮已连接到已连接的输入,因此它可能会导致中断。

第三种方法是配置一个计时器以某种速率(例如,1000x/秒)中断处理器,并让该中断的处理程序检查按钮的状态并对其采取行动。

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

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

  1. 每个合法的开关事件都包含一个从 0 到 900us(微秒)的时间间隔,在此期间开关可以任意关闭和重新打开,然后是至少 1.1ms 的时间间隔,在此期间开关将保持关闭状态,然后是一个时间间隔0~900us,在此期间开关可以任意分闸和重合,随后有至少1.1ms的时间间隔使开关分闸。
  2. 在任何未忽略的开关打开或关闭后,软件必须在 950us 内忽略开关的状态。
  3. 允许软件任意计数或忽略在上述要求的消隐间隔之外发生但持续时间小于 1.1 毫秒的开关事件。
  4. 软件上报的计数必须在开关稳定“闭合”后的 1.99ms 内有效。

执行此要求的最简单方法是以 1,000x/秒的速度观察交换机的状态;如果在前一个状态为“打开”时看到“关闭”,则增加计数器。非常简单易行;即使开关以各种奇怪的方式打开和关闭,在真实事件之前和之后的 900us 期间,软件也不会在意。

可以使用开关输入触发的中断和定时器来更快地响应开关输入,同时满足所需的消隐要求。最初,输入将在下次开关闭合时触发。一旦中断被触发,软件会禁用它,但会设置一个定时器以在 950us 后触发中断。一旦该计时器到期,它将触发一个中断,该中断将在下次开关“打开”时触发中断。该中断将依次禁用开关中断并再次将定时器设置为 950us,因此定时器中断将再次重新启用开关中断。有时这种方法很有用,但软件比简单的轮询方法复杂得多。当基于计时器的方法足够时,通常更可取。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-16
    • 1970-01-01
    • 2014-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多