This episode dissects threading, multiprocessing, and asyncio along with their models and pitfalls. You'll also learn modern async patterns with asyncio TaskGroups in Python 3.11 plus alternatives like trio and anyio.

Applications that handle many things at once are a real need. Episode 15 dissects Python's three concurrency approaches: threading, multiprocessing, and asyncio. Each has its own model, strengths, and pitfalls.
We'll also learn modern async patterns with asyncio.TaskGroup in Python 3.11 plus alternatives like trio and anyio. With this understanding, you can pick the right approach for each problem.
Before choosing a concurrency tool, recognize the type of workload:
import time
def io_bound():
time.sleep(1)
def cpu_bound():
total = 0
for i in range(10_000_000):
total += i
return totaltime.sleep(1) simulates I/O work — waiting on network or disk. A large loop simulates CPU work. I/O-bound fits threading and asyncio; CPU-bound fits multiprocessing. Choosing the wrong approach makes your application slow even with concurrency.
Threading runs within one process and shares memory, but is limited by the GIL for CPU code:
import threading
import time
def kerja(nama):
time.sleep(1)
print(f"{nama} selesai")
mulai = time.perf_counter()
t1 = threading.Thread(target=kerja, args=("A",))
t2 = threading.Thread(target=kerja, args=("B",))
t1.start()
t2.start()
t1.join()
t2.join()
print(time.perf_counter() - mulai)threading.Thread(target=kerja, args=("A",)) creates a new thread. Because time.sleep releases the GIL, two threads finish their work concurrently — total time far below 2 seconds. For I/O-bound work, threading is effective.
Multiprocessing uses separate processes, each with its own interpreter:
from multiprocessing import Pool
def hitung(n):
total = 0
for i in range(n):
total += i
return total
if __name__ == "__main__":
with Pool(4) as pool:
hasil = pool.map(hitung, [10_000_000] * 4)
print(hasil)with Pool(4) as pool: creates four processes. pool.map distributes the work. Unlike threads, processes have their own GIL, so CPU computation runs in parallel. Note the if __name__ == "__main__" guard, which is required for multiprocessing on many systems.
asyncio runs many tasks in a single thread using an event loop:
import asyncio
async def kerja(nama):
await asyncio.sleep(1)
return f"{nama} selesai"
async def utama():
hasil = await asyncio.gather(
kerja("A"),
kerja("B"),
kerja("C"),
)
print(hasil)
asyncio.run(utama())async def kerja(nama) defines a coroutine and await asyncio.sleep(1) pauses without blocking. asyncio.gather runs many coroutines concurrently. asyncio.run(utama()) starts the event loop. This model is very efficient for thousands of concurrent connections.
Python 3.11 introduced asyncio.TaskGroup to manage a group of tasks in a structured way:
import asyncio
async def kerja(nama):
await asyncio.sleep(1)
return f"{nama} selesai"
async def utama():
async with asyncio.TaskGroup() as grup:
tugas = [grup.create_task(kerja(nama)) for nama in ["A", "B", "C"]]
for t in tugas:
print(t.result())
asyncio.run(utama())async with asyncio.TaskGroup() as grup: creates a task group. grup.create_task(...) adds tasks that run concurrently. The async with block waits for all of them to finish, and cancels everything if one fails — much better error management than gather.
anyio provides a single API that runs on top of both asyncio and trio:
pip install anyioimport anyio
async def kerja(nama):
await anyio.sleep(1)
print(f"{nama} selesai")
async def utama():
async with anyio.create_task_group() as grup:
grup.start_soon(kerja, "A")
grup.start_soon(kerja, "B")
anyio.run(utama)anyio.create_task_group() creates a task group that can run on any backend. FastAPI and Starlette use anyio, so you can choose a backend without changing the API. This is a good portability investment.
Key takeaways:
In the next episode, episode 16, we'll cover performance tuning and profiling — profilers like cProfile and pyinstrument, sampling profilers and flame graphs, hot path optimization, native extensions with Cython, and when to use PyPy. Your application will run much faster!