Week 11 - The GIL, Free-Threaded Python, and the Concurrency Model¶
11.1 Conceptual Core¶
- The Global Interpreter Lock serializes Python bytecode execution. It does not serialize C extensions that release it (NumPy, PyTorch,
time.sleep, most I/O). This is why "Python is single-threaded" is wrong on the parts that matter. - CPU-bound, pure-Python → multiprocessing or free-threaded build (PEP 703).
- CPU-bound, native (NumPy/torch) → threads are fine; the GIL is released.
- I/O-bound → asyncio (preferred) or threads.
11.2 Mechanical Detail¶
- The GIL is a single mutex around the interpreter state. Released on I/O syscalls and on every ~5ms timeslice (
sys.setswitchinterval). Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADSin C extensions: how NumPy/torch escape.- PEP 703 free-threaded build (3.13 experimental, 3.14 stable target): per-object locking, biased reference counting, deferred reference counting for immortal objects. Trade-off: ~10–20% single-threaded slowdown, true parallel threads. Build with
--disable-gilor usepython3.13t. - PEP 684 per-interpreter GIL: subinterpreters with their own GIL,
interpretersmodule (PEP 734, 3.13+). Promising for embedded multitenancy. threading.Lock,RLock,Semaphore,Condition,Event,Barrier. The atomicity guarantees of CPython ondict/listops are implementation details, not language-level - under free-threaded these change. Always use a lock if you require atomicity.
11.3 Lab - "GIL Awareness"¶
- Compute primes up to 1M three ways: (a) single thread, (b)
threadingwith 8 threads, (c)multiprocessingwith 8 procs. Bench all three on stock CPython. - Run (b) on
python3.13t(free-threaded). Compare. - Replace the prime-test inner loop with a NumPy expression. Re-run (b) on stock CPython. Note the GIL-release effect.
- Capture
py-spy recordflame graphs for each. Identify GIL contention visually.
11.4 Idiomatic & Linter Drill¶
- Enable
ruffASYNC. Catchtime.sleepinsideasync def, blocking I/O inside async, etc.
11.5 Production Hardening Slice¶
- Add
py-spycontinuous profiling to your CI'd service. On every PR, attach a flame graph artifact.