Skip to content

Cooperative scheduling

Category: Scheduling · Status: stub · Lessons: chapter 06, Async (planned)

One line: A task runs until it gives way — at an await, a yield or a blocking call — so switches happen only at known points, and one task that never gives way stalls all the others.

Also called: cooperative multitasking, non-preemptive scheduling.

How it connects

flowchart LR
  n_blocking_the_event_loop["Blocking the event loop"]
  n_cooperative_scheduling["Cooperative scheduling"]
  n_preemptive_scheduling["Preemptive scheduling"]
  n_scheduling_policy["Scheduling policy"]
  n_suspension_point["Suspension point"]
  n_cooperative_scheduling -->|can cause| n_blocking_the_event_loop
  n_cooperative_scheduling ---|vs| n_preemptive_scheduling
  n_cooperative_scheduling -->|is a| n_scheduling_policy
  n_cooperative_scheduling -->|uses| n_suspension_point
  classDef center stroke-width:3px
  class n_cooperative_scheduling center
  classDef outside stroke-dasharray: 4 3
  class n_blocking_the_event_loop,n_preemptive_scheduling,n_scheduling_policy,n_suspension_point outside

In each language

Rust tokio::task::yield_now yields execution back to the runtime, which schedules the other pending tasks
Go Before Go 1.14 ↗, a loop without function calls could hold up the scheduler; runtime.Gosched still yields on request
Python await asyncio.sleep(0) lets other tasks run
C# await Task.Yield()
JavaScript Code runs to completion ↗; other code runs only after an await or a return to the event loop
Kotlin A coroutine keeps its thread until it suspends; yield() suspends only to let other coroutines run
Swift Task.yield() suspends the current task so that other tasks can run

Where to read more