asyncio Condition wait notify pattern in Python

Coordinate coroutines with asyncio.Condition: workers wait for notifications and the main task notifies one or all of them.

Medium Python 3.8+ Aug 9, 2026 Concurrency & performance 14 views 0 copies

Python code

31 lines
Python 3.8+
import asyncio


async def worker(condition, name):
    async with condition:
        print(f"{name} waiting...")
        await condition.wait()
        print(f"{name} notified!")


async def main():
    condition = asyncio.Condition()
    tasks = [asyncio.create_task(worker(condition, f"worker-{i}")) for i in range(3)]

    await asyncio.sleep(0.1)  # let workers acquire the condition and wait

    async with condition:
        print("notifying one worker...")
        condition.notify(1)

    await asyncio.sleep(0.1)

    async with condition:
        print("notifying all workers...")
        condition.notify_all()

    await asyncio.gather(*tasks)


if __name__ == "__main__":
    asyncio.run(main())

Output

stdout
worker-0 waiting...
worker-1 waiting...
worker-2 waiting...
notifying one worker...
worker-0 notified!
notifying all workers...
worker-1 notified!
worker-2 notified!

How it works

The asyncio.Condition provides an async context manager that acquires the associated lock before allowing await condition.wait(). When wait() is called, the coroutine releases the lock and suspends until notify() or notify_all() is called. The notify(1) wakes up one waiting coroutine, while notify_all() wakes all. Because the workers are created with create_task, they run concurrently, and the explicit asyncio.sleep calls in main give them time to start waiting before notifications occur. This pattern is useful for signaling between coroutines without busy-waiting.

Common mistakes

  • Calling `condition.wait()` outside the `async with condition:` block, causing a RuntimeError.
  • Forgetting to `await` the `condition.wait()` call, suspending the coroutine incorrectly.
  • Not using `async with` when calling `notify()` or `notify_all()`, leading to a missing lock context.
  • Assuming notifications are queued; if no waiter is present, the notification is lost.

Variations

  1. Use `asyncio.Event` for simpler broadcast signaling when you don't need per-condition locking.
  2. Use `asyncio.Queue` to explicitly pass values between producer and consumer coroutines.

Real-world use cases

  • Coordinating multiple background workers that should pause until a resource becomes available.
  • Implementing a publisher-subscriber pattern where one task notifies several consumers of new data.
  • Synchronizing startup of parallel services in a simulator or test harness before proceeding.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Concurrency & performance

Related tutorials and quizzes for this topic.