Skip to content
BytePatterns

Blocking the Event Loop

Concurrency: lesson 14 of 15

One thread runs everything, so one rude call stops the world.

Lesson 14 of 15 · 5 min

Blocking the Event Loop

Step 1 of 9

An event loop is one thread. Whatever is running owns it until it gives it back.

The Idea

An event loop is cooperative: one thread, one task running at a time, and control only changes hands at an await. Concurrency comes from tasks that yield while they wait. A call that does not yield — a blocking read, a tight computation — holds the only thread, and everything else stops.

Real-World Example

One clerk serving a queue by taking each customer as far as their paperwork allows, then calling the next while forms are filled in. Concurrency, with one clerk. Then someone asks them to count a jar of coins.

The Code

import asyncio, time

async def gauge(depth):
    await asyncio.sleep(0.1)              # yields the thread to the loop
    return depth

async def rude(depth):
    time.sleep(0.1)                       # holds the only thread
    return depth

async def race(worker):
    start = time.perf_counter()
    await asyncio.gather(worker(3), worker(7))
    return round(time.perf_counter() - start, 1)

print(asyncio.run(race(gauge)))           # 0.1 -- the two waits overlapped
print(asyncio.run(race(rude)))            # 0.2 -- they queued up

Python

Your turn

Put the steps in the right order.

  1. The loop starts the second task while the first is waiting
  2. A task runs until it reaches an await
  3. The first task resumes where it left off
  4. Its awaited operation reports that it is ready

Mini quiz

1 / 3

`await asyncio.sleep(1)` differs from `time.sleep(1)` because it:

New lessons land every few weeks

Leave an address and we will tell you when the next one is up. That is the only reason we will use it.

One address, stored so we can email you. Nothing else, ever.