Significance of Sleep(0)

Significance of Sleep(0)

According to MSDN's documentation for Sleep:

A value of zero causes the thread to
relinquish the remainder of its time
slice to any other thread that is
ready to run. If there are no other
threads ready to run, the function
returns immediately, and the thread
continues execution.

The important thing to realize is that yes, this gives other threads a chance to run, but if there are none ready to run, then your thread continues -- leaving the CPU usage at 100% since something will always be running. If your while loop is just spinning while waiting for some condition, you might want to consider using a synchronization primitive like an event to sleep until the condition is satisfied or sleep for a small amount of time to prevent maxing out the CPU.

sleep 0 has special meaning?

Yes, for a couple of reasons, first of all, (mri) ruby threads are wrappers around native threads with an additional GVL lock.

Essentially what ruby is doing when you call sleep is calling the underlying, native, platform dependent sleep and releasing the GVL so that other running threads can acquire it. So sleep(0) is both yielding to other native threads that may be waiting to be executed as well as releasing the current thread's hold on the GVL which would otherwise keep the Ruby VM from executing.

Here's a quick rundown of how you can see this from mri source:

  1. We get the definition of Kernel sleep from https://github.com/ruby/ruby/blob/trunk/process.c#L7542, which we see is implemented in c in the function rb_f_sleep
  2. Next we go to rb_f_sleep and see that in the case of a single argument it calls rb_thread_wait_for
  3. Going to the rb_thread_wait_for definition we see a call to sleep_timeval
  4. sleep_timeval has a call to native_sleep
  5. native_sleep is platform dependent and implemented in thread_pthread.c and thread_win32.c for posix and windows systems respectively. In either case we see calls to GVL_UNLOCK_BEGIN here and here

EDIT

To be more precise:

Windows:

The windows implementation of native_sleep uses WaitForMultipleObjects which does indeed yield the remaining time slice, see: Does WaitForSingleObject give up a thread's time slice?

Posix:

The posix implementation uses pthread_cond_timedwait, which blocks the currently running thread.

Either way, the main thing to note here is that Ruby threads use the underlying thread blocking mechanisms of the OS and release the GVL with any call to sleep, allowing other threads to take control.

How do I obtain Sleep(0) like behaviour in Linux

Try sched_yield from "sched.h", that is created just for what you want to do.

If that doesn't work for whatever reason - try usleep(1) - That will yield at least 1 microsecond delay (may be more), which in turn triggers a context switch (if any thread is waiting).

What is the purpose of the sleep() function in a Thread?

Use of sleep() function (and it's friends) usually indicate design flaw. The rare exceptions are sleeps used in debugging.

The common misguided usages of sleep include an attempt to time events to a certain time (bad, because no one guarantees that sleep will take exactly that many units as prescribed on non-RT systems), attempt to wait for some events (bad, because to wait for event you should use specific waiting functions available with your threading library) or an attempt to yield resources - bad, because if you have nothing to do, just exit the thread.

How important is it to call Sleep() in a infinite while loop?

It depends on what's happening in your loop. If it is busy-waiting and usually does nothing, then the Sleep call (this looks like Windows, so its a 1ms delay) will yield the scheduler and might prevent the thread from spinning the CPU core and turning on your CPU fan. If it always has something to do, then the 1ms sleeps will indeed add up and slow down your execution. I suggest watching the CPU usage in task manager with and without the Sleep call, and benchmark your code with known input to see what if it actually takes longer.

is Queue empty method broken?

Two possible solutions:

  1. Use queue.Queue instead of multiprocessing.Queue:
    Some differences in doc between them:

They differ in that Queue lacks the task_done() and join() methods introduced into Python 2.5's queue.Queue class.

from queue import Queue
q = Queue()
print(q.empty())
q.put("a")
print(q.empty())

  1. Or just like @Hans Musgrave said in comment.time.sleep(1) is not guaranteed.You could use time.sleep(0) instead:
from multiprocessing import Queue
import time
q = Queue()
print(q.empty())
time.sleep(0)
q.put("a")
print(q.empty())

All of them give me:

True
False

About why sleep(0), A value of zero causes the thread to relinquish the remainder of its time slice to any other thread that is ready to run. If there are no other threads ready to run, the function returns immediately, and the thread continues execution
cpu gives up resources, to execute q.emety() task.That's what I think.

The stable method is to use queue.Queue or queues.SimpleQueue.

When to use Task.Delay, when to use Thread.Sleep?

Use Thread.Sleep when you want to block the current thread.

Use await Task.Delay when you want a logical delay without blocking the current thread.

Efficiency should not be a paramount concern with these methods. Their primary real-world use is as retry timers for I/O operations, which are on the order of seconds rather than milliseconds.



Related Topics



Leave a reply



Submit