What the GIL is, and why it exists
coreintermediateThe GIL is a mutex inside CPython letting only one thread execute Python bytecode at a time — even on multiple cores, two threads never run Python code simultaneously. It exists because reference counting is not thread-safe without it.
Think of it as
Picture CPython's memory management as a shared ledger every object's reference count is written into. Without one rule about who can write at a time, two threads updating the same count simultaneously could corrupt it — an object freed too early, or never freed at all. The GIL is that rule: only the thread currently holding it may touch the ledger, so no two threads ever race on a refcount update.
What we're doing: Confirm this interpreter runs the standard, GIL-enabled build (not a free-threaded 3.13+ build) before drawing any conclusions from timing comparisons.
- 4
- sys._is_gil_enabled() is the reliable way to check — do not assume from the Python version number alone, since free-threading is opt-in even on 3.13+.
Python: 3.14.3
GIL enabled: TrueWhy this works: This confirms the environment every other timing claim in this section was measured on: a standard CPython 3.14.3 build with the GIL enabled, not the experimental free-threaded build. The CPU-bound-vs-I/O-bound timings in the paired concept only make sense with this confirmed — a free-threaded build would show CPU-bound threading actually scale, which is the whole point PEP 703 exists to demonstrate.
Assuming the GIL means Python threads are pointless
Wrong
Better
What you see: Concluding "the GIL means threads never help" and avoiding threading.Thread / ThreadPoolExecutor entirely, including for I/O-bound work where it would have helped.
Why: The GIL only blocks concurrent execution of Python BYTECODE. Blocking operations that hand control to the OS — time.sleep(), socket reads, file I/O — release the GIL for the duration of the wait, letting another thread run. The GIL's real constraint is specifically on CPU-bound Python code, covered in the paired concept.
- 4 threads — in one process
- the GIL — held by exactly one thread at a time
- 1 thread runs bytecode — the other 3 wait their turn
Where the GIL is, and is not, a CPython implementation detail
Remember: The GIL is one mutex per CPython process, letting only one thread run bytecode at a time. A CPython detail, not a language rule.
See also: reference counting · gil effects and when to use what

