Is it Really Busy Waiting If I Thread.Sleep()?

偶尔善良 提交于 2019-12-05 15:17:21

问题


My question is a bit nit-picky on definitions:

Can the code below be described as "busy waiting"? Despite the fact that it uses Thread.Sleep() to allow for context switching?

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

PS - The current definition for busy waiting in Wikipedia suggests that it is a "less wasteful" form of busy waiting.


回答1:


Any polling loop, regardless of the time between polling operations, is a busy wait. Granted, sleeping a few milliseconds is a lot less "busy" than no sleep at all, but it still involves processing: thread context switches and some minimal condition checking.

A non-busy wait is a blocking call. The non-busy version of your example would involve waiting on a synchronization primitive such as an event or a condition variable. For example, this pseudocode:

// 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();
}

The difference here is that there is no periodic polling. The Wait call blocks and the thread is never scheduled until the event is set.




回答2:


That's not busy waiting. Busy waiting, or spinning, involves the opposite: avoiding context switching.

If you want to allow other threads to run, if and only if other threads are ready to run, to avoid deadlock scenarios in single threaded CPUs (e.g., the current thread needs work_is_ready to be set to true, but if this thread doesn't give up the processor and lets others run, it will never be set to true), you can use Thread.Sleep(0).

A much better option would be to use SpinWait.SpinUntil

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

SpinWait emits a special rep; nop (repeat no-op) or pause instruction that lets the processor know you're busy waiting, and is optimized for HyperThreading CPUs. Also, in single core CPUs, this will yield the processor immediately (because busy waiting is completely useless if there's only one core).


But spinning is only useful if you're absolutely sure you won't be waiting on a condition for longer than it would take the processor to switch the context out and back in again. I.e., no more than a few microseconds.

If you want to poll for a condition every few milliseconds, then you should use a blocking synchronization primitive, as the wiki page suggests. For your scenario, I'd recommend an AutoResetEvent, which blocks the thread upon calling WaitOne until the event has been signaled (i.e, the condition has become true).

Read also: Overview of Synchronization Primitives




回答3:


It depends on the operating system and the exact number of milliseconds you are sleeping. If the sleep is sufficiently long that the operating system can switch to another task, populate its caches, and usefully run that task until your task is ready-to-run again, then it's not busy waiting. If not, then it is.

To criticize this code, I would say something like this: "This code may busy wait if the sleep is too small to allow the core to do useful work between checks. It should be changed so that the code that makes this code need to do work triggers that response."

This poor design creates a needless design problem -- how long should the sleep be? If it's too short, you busy wait. If it's too long, the work sits undone. Even if it's long enough that you don't busy wait, you force needless context switches.




回答4:


When your code is sleeping for a moment, technically it will be in sleep state freeing up a CPU. While in busy waiting your code is holding the CPU until condition is met.

Can the code below be described as "busy waiting"? Despite the fact that it uses Thread.Sleep() to allow for context switching?

It is not busy waiting, rather polling which is more performant that busy waiting. There is a difference between both

Simply put, Busy-waiting is blocking where as Polling is non-blocking.



来源:https://stackoverflow.com/questions/24630624/is-it-really-busy-waiting-if-i-thread-sleep

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!