Learn with diagrams, code, systems and practical examples.
Async and Concurrency
Understand when async code helps and when it adds unnecessary complexity.
Applications often wait on network or disk operations, and concurrency can improve throughput when tasks spend significant time waiting.
Start with the idea
asyncio lets one thread make progress on other tasks while awaiting I/O. async def defines a coroutine and await pauses that coroutine until an awaitable operation can continue.
Small working example
Run this example first. Do not change several things at once; confirm the basic behavior, then experiment.
import asyncio
async def main():
await asyncio.sleep(0.1)
print("done")
asyncio.run(main()) asyncio lets one thread make progress on other tasks while awaiting I/O. async def defines a coroutine and await pauses that coroutine until an awaitable operation can continue.
- Async is mainly useful for waiting-heavy workloads.
- await yields control cooperatively.
- Concurrency choices should match the workload.
doneThe example is intentionally small. Focus on the chapter’s main idea before adding extra syntax or framework code.
Common beginner mistake
Using async for CPU-heavy work and expecting it to make calculations automatically run in parallel.
Use async primarily for I/O-bound concurrency and choose other strategies for CPU-bound workloads.
Quick recap
- Async is mainly useful for waiting-heavy workloads.
- await yields control cooperatively.
- Concurrency choices should match the workload.
Try it yourself
These are deliberately small. If you can complete them without copying the example, you are ready to continue.
- Run two sleeping coroutines concurrently.
- Identify whether a sample task is I/O-bound or CPU-bound.