Skip to content

What does one blocking call do to every other task?

Level: 201 · anyone whose async server went quiet for a second at a time

Stub — a question and its expected answers, not yet a lesson. No program behind this page has been written or run, so nothing on it has been through the check that backs every finished page. The table is what the finished lesson is expected to find, and every cell is unverified until a program prints it. (Not machine-checked here.)

One line: A call that blocks the thread — a sleep, a synchronous read, a CPU loop — inside an async task stops the event loop, and with it every task on it, for as long as the call takes; nothing on the loop can run until it returns, and the fix is to move the call to a thread that is not the loop's.

The question

Ten tasks each print once a tenth of a second. One task calls a blocking sleep(1). For that second, the other nine print nothing — the page counts their prints in that window and finds zero. Then the blocking call is moved off the loop (spawn_blocking, run_in_executor, to_thread) and the count is nine each. Go's column is the contrast: a blocking call in a goroutine costs a thread, not the program.

What each language is expected to say

Expected answer, to be verified by the program
Rust std::thread::sleep in a tokio task stalls its worker; spawn_blocking is the fix (link, not run; std has no runtime)
Go a blocking call in a goroutine blocks one OS thread and the runtime hands the others new work
C a blocking read inside the hand-written loop stalls everything, which is why the loop uses non-blocking descriptors
C++ the same as C
Java on a virtual thread a blocking call unmounts the carrier — except inside synchronized before Java 24
Python time.sleep(1) in a coroutine stalls the loop; await asyncio.to_thread(time.sleep, 1) does not

What the programs have to show

  • ten ticking tasks and one blocking call: the tick counts during the blocked second
  • the same with the call moved off the loop
  • Go's goroutines ticking through a blocking call in another goroutine

See also