Python

How does Python 3.13's free-threaded mode achieve true multi-core parallelism without the Global Interpreter Lock (GIL)?

December 3, 2025

download ready
Thank You
Your submission has been received.
We will be in touch and contact you soon!

Replaces single global refcount with per-thread reference counting tables, eliminating atomic contention. Deferred deallocation queue handles cross-thread object cleanup safely. ThreadState tracks per-thread objects, avoiding GIL serialization. 3x speedup on CPU-bound multithreading workloads. Install via uv python install 3.13t.

Code

# Install free-threaded Python
# uv python install 3.13t

import sysconfig
import threading
import time

print(f"GIL: {sysconfig.get_config_var('Py_GIL_DISABLED')}")  # 1 = free-threaded

def cpu_work():
    total = 0
    for i in range(10**8):  # CPU intensive
        total += i * i
    return total

# 8 threads true parallelism (no GIL bottleneck)
start = time.time()
threads = [threading.Thread(target=cpu_work) for _ in range(8)]
for t in threads: t.start()
for t in threads: t.join()
print(f"Free-threaded: {time.time() - start:.2f}s")  # ~0.5s vs 4s GIL
      
Hire Now!

Need Help with Python Development ?

Work with our skilled python developers to accelerate your project and boost its performance.
**Hire now**Hire Now**Hire Now**Hire now**Hire now

How does Python 3.13's free-threaded mode achieve true multi-core parallelism without the Global Interpreter Lock (GIL)?

Replaces single global refcount with per-thread reference counting tables, eliminating atomic contention. Deferred deallocation queue handles cross-thread object cleanup safely. ThreadState tracks per-thread objects, avoiding GIL serialization. 3x speedup on CPU-bound multithreading workloads. Install via uv python install 3.13t.

Code

# Install free-threaded Python
# uv python install 3.13t

import sysconfig
import threading
import time

print(f"GIL: {sysconfig.get_config_var('Py_GIL_DISABLED')}")  # 1 = free-threaded

def cpu_work():
    total = 0
    for i in range(10**8):  # CPU intensive
        total += i * i
    return total

# 8 threads true parallelism (no GIL bottleneck)
start = time.time()
threads = [threading.Thread(target=cpu_work) for _ in range(8)]
for t in threads: t.start()
for t in threads: t.join()
print(f"Free-threaded: {time.time() - start:.2f}s")  # ~0.5s vs 4s GIL