Concurrency
Global Interpreter Lock (GIL)
Understanding the GIL — why Python threads are not truly parallel for CPU-bound work, and choosing the right concurrency strategy.
Interview: Very common interview topic — must explain the GIL, its implications, and workarounds.
The Global Interpreter Lock (GIL) is a mutex in CPython that allows only one thread to execute Python bytecode at a time. This means CPU-bound threads cannot achieve true parallelism on multi-core machines, but I/O-bound threads still benefit because the GIL is released during I/O operations.
How the GIL Works
- Only one thread can hold the GIL at any time
- The GIL is released during I/O operations (file, network, sleep)
- Threads switch after a time interval or when they do I/O
- Python 3.2+ uses time-based switching (5ms default)
Impact on Different Workloads
- I/O-bound (helpful): Threads still help — GIL released during I/O wait
- CPU-bound (harmful): Threads actually slower than sequential due to GIL overhead
- Multiprocessing: Each process has its own GIL — true parallelism
- asyncio: Single thread, cooperative multitasking — no GIL issues
Workarounds
- multiprocessing: Separate processes, each with own GIL
- C extensions: NumPy releases GIL for heavy computations
- asyncio: Cooperative concurrency without threads
- Python 3.13+: Free-threaded mode (no-GIL) available experimentally
Interview Insight
The classic interview answer: "Threads help with I/O-bound tasks, not CPU-bound tasks, because of the GIL. For CPU-bound work, use multiprocessing or asyncio. The GIL exists to protect CPython's reference counting memory management."
Use Cases
Choosing concurrency strategy — understand GIL to pick threads vs processes vs async
I/O-bound optimization — use threads for network, file, database operations
CPU-bound optimization — use multiprocessing for computation-heavy tasks
Library design — release GIL in C extensions for parallel computation
Performance debugging — identify when GIL is the bottleneck
Common Mistakes
Using threads for CPU-bound work expecting speedup — GIL prevents true parallelism
Not knowing the GIL is released during I/O — threads help with I/O-bound work
Thinking the GIL makes Python thread-safe — you still need locks for shared data
Not considering multiprocessing as an alternative for CPU-bound work
Forgetting that C extensions (NumPy) can release the GIL for parallel computation