Courses/Concurrency & Parallelism

Concurrency & Parallelism

Threads for I/O

Use threading when you wait on the network or disk.

Threads share memory and are great for I/O-bound work. The GIL means only one thread runs Python bytecode at a time — so threads do NOT speed up CPU-bound code.

import threading

results = []

def square(n):
    results.append(n * n)

threads = [threading.Thread(target=square, args=(i,)) for i in range(1, 5)]
for t in threads: t.start()
for t in threads: t.join()

print(sorted(results))  # [1, 4, 9, 16]

**Rules of thumb**

  • I/O-bound (network, disk) → threads or asyncio.
  • CPU-bound (math, parsing) → multiprocessing (each process has its own GIL).
  • Always .join() threads or use a context like concurrent.futures.ThreadPoolExecutor.

> 🧪 This topic is concept-only in the browser sandbox — Pyodide runs in a single Web Worker and cannot spawn OS threads. Try the snippet in real CPython.

Concept lesson

This topic relies on OS features the in-browser Python sandbox can't run (threads, subprocesses, sockets). Read the examples here, then try them in real CPython on your machine.

Sign in to track your progress across lessons.