Python

Global Interpreter Lock (GIL)

The Global Interpreter Lock is a single mutex wrapped around the entire Python interpreter, so only one thread can execute Python bytecode at a time. Covered in ECE459 L11 as the canonical example of coarse-grained locking.

Why one giant lock?

Coarse-grained locking is the easiest thing that can possibly work: one lock means no deadlocks, minimal memory overhead, and trivial implementation. L11’s framing: “As much as this ruins performance, correctness is more important.” The GIL made CPython’s C extension ecosystem possible without per-object locks.

Implications for threaded Python

  • Threading only helps when threads are waiting on I/O (the GIL is released during blocking syscalls)
  • Any CPU-bound threaded program is slower than the sequential version, because the interpreter slows everything down on top of paying context-switch cost
  • This is the main reason most scripting languages have poor parallel performance; Python is just the famous example

Not unique to Python

OS kernels have made the same call. Linux had a Big Kernel Lock from the advent of SMP support until around 2011. Mach microkernel had one too. Correctness first, parallelism later.

Removing the GIL

CPython is landing a free-threaded build via PR #116338 (PEP 703). The price is per-object locking and more complex reference counting, which is exactly the trade-off L11 warns about when moving from coarse to fine-grained.

Resources: