bigonotes
CS ConceptsOS Fundamentals

sleep() vs wait()

Why sleep() keeps your locks while wait() releases them, and where yield() fits in.

3 min readLast updated OS Fundamentals

sleep() and wait() both move a thread into the Waiting state, but they mean very different things. sleep() is a timed pause that keeps any locks the thread holds. wait() is for coordination: it releases the lock and waits until another thread signals. Mixing them up is a common source of stalls in concurrent code.

In Python, these are time.sleep() and threading.Condition.wait().

sleep() keeps the lock, waits for a timer, then goes back to the ready queue on its own.

wait() releases the lock and waits until another thread calls notify() / notify_all() (or an optional timeout expires).

sleep(): "wake me after N seconds"#

A sleeping thread simply gives up the CPU for a fixed time.

import time

time.sleep(5)  # don't need the CPU for 5 seconds
  • The thread moves to Waiting (a timed wait).
  • It does not release any locks it holds.
  • When the timer expires, the OS moves it back to Ready. Nobody has to wake it.

wait(): "I can't continue until someone tells me"#

A waiting thread hands back the lock and sleeps until another thread signals that the condition may have changed.

import threading

cond = threading.Condition()
data_ready = False

def consumer():
    with cond:
        while not data_ready:
            # Releases cond's lock and sleeps; re-acquires it before returning
            cond.wait()
        # data_ready is True and this thread holds the lock again
        print("got data")

def producer():
    global data_ready
    with cond:
        data_ready = True
        cond.notify_all()  # wake the waiters

t = threading.Thread(target=consumer)
t.start()
producer()
t.join()
  • The thread moves to Waiting.
  • It releases the condition's lock, so other threads can enter and change the condition.
  • It stays waiting until another thread calls notify() or notify_all() on the same condition (or until the timeout, if you call wait(timeout)).
  • You must hold the lock to call wait(), or Python raises RuntimeError.
  • Always check the condition in a while loop (or use cond.wait_for(predicate)): threads can wake spuriously, or another thread may have consumed the condition first.

Why the lock difference matters#

Suppose Thread 1 holds lock A and then pauses. What happens to Thread 2, which also needs A, depends on how Thread 1 pauses:

Thread 1 calls sleep(5) Thread 1 calls wait()
Before pausing Holds lock A Holds lock A
Lock A while paused Still held Released
Thread 2 needs A Blocked for 5 s Proceeds now

Calling sleep() while holding a lock is usually a bug: everyone else waits for no reason. wait() exists precisely so the thread that will satisfy the condition can get in.

yield(): a hint, not a wait#

Some runtimes offer a "yield" call that offers the CPU to other threads without waiting for anything. In Python, time.sleep(0) plays this role (on Unix, os.sched_yield() is the direct system call).

import time

time.sleep(0)  # willing to give up the CPU, but not required to

The thread stays Ready (runnable) and only hints that others may go first. The scheduler is free to ignore it. You'll rarely need it.

Comparison#

The three calls differ in state, locks and who wakes the thread.

sleep() wait() yield
State Waiting (timed) Waiting Ready
Releases lock? No Yes N/A
Wakes when Timer expires notify()/notify_all() or timeout Scheduler decides
Purpose Timed pause Coordinating threads Scheduler hint
Typical use Polling delays, simple throttling Producer–consumer, condition waiting Almost never

Key takeaways#

  • sleep() pauses for a fixed time and keeps every lock it holds.
  • wait() releases the lock, waits for a signal, and re-acquires the lock before returning.
  • Always call wait() while holding the condition's lock, in a while loop that re-checks the condition.
  • Sleeping while holding a lock is almost always a bug.
  • Yielding is only a hint; the thread stays runnable.

Found a mistake? Tell me on LinkedIn ↗

Further reading#