For decades, CPython's Global Interpreter Lock (GIL) meant only one thread could execute Python code at a time. Threads helped with waiting on I/O, but CPU-heavy work needed multiprocessing or native extensions to use multiple cores.
Python 3.14 is the first release where the free-threaded build, Python without the GIL, is officially supported. It is still a separate build rather than the default, but it is now a real option.
What changes
In the free-threaded build, multiple threads can run Python code truly in parallel on different CPU cores.
from concurrent.futures import ThreadPoolExecutor
def cpu_work(n):
return sum(i * i for i in range(n))
with ThreadPoolExecutor(max_workers=4) as pool:
results = list(pool.map(cpu_work, [5_000_000] * 4))On the standard build this runs roughly one task at a time. On the free-threaded build, the four tasks can run on four cores.
When it helps
- CPU-bound work in threads: parsing, data transformation, simulations, image processing in pure Python.
- Workloads that used multiprocessing only to get parallelism, and paid for it with process start-up and data copying.
- Servers mixing I/O and CPU work in threads.
Reported speed-ups for multi-threaded CPU-bound code are substantial on multi-core machines, though far from linear.
When it does not
- Single-threaded code runs somewhat slower on the free-threaded build, because of the extra work needed for thread safety.
- I/O-bound code was already fine with threads or asyncio.
- NumPy-style workloads that already release the GIL inside native code may see little change.
Compatibility: check your extensions
C extensions must be built for the free-threaded ABI. Many popular packages provide compatible wheels, but coverage is uneven. If an extension is not marked as free-threading safe, Python may re-enable the GIL at import time and print a warning.
Try it with uv
uv venv --python 3.14t
uv run python -c "import sys; print('GIL enabled:', sys._is_gil_enabled())"The t suffix selects the free-threaded build.
Thread safety is now your problem
The GIL hid many race conditions. Without it, shared mutable state needs real protection:
import threading
lock = threading.Lock()
counter = 0
def increment():
global counter
with lock:
counter += 1Prefer designs that avoid shared state: pass data to workers and collect results, or use queues.
How to evaluate it
- Benchmark your real workload on both builds.
- Run your test suite on the free-threaded build, ideally under stress with many threads.
- Check that every native dependency supports it.
Key takeaways
- Python 3.14 officially supports a free-threaded build without the GIL.
- It speeds up CPU-bound multi-threaded code but slows single-threaded code slightly.
- Native extensions must support it, or the GIL may be re-enabled.
- Benchmark and test carefully, and protect shared state with locks.