1. What is the Python Global Interpreter Lock (GIL) and how does it affect multi-threading?
❓ Context: Explain what the GIL is in CPython, why it prevents true parallel execution of CPU-bound threads, and how multiprocessing solves it.
The Global Interpreter Lock (GIL) is a mutex (mutual exclusion lock) used by CPython (the standard Python implementation) that allows only one thread to execute Python bytecode at a time, even on multi-core processors.
Why does the GIL exist?
CPython's memory management uses reference counting. When an object's reference count drops to zero, it is garbage collected. If multiple threads simultaneously increment or decrement reference counts without locking, memory corruption and race conditions occur. The GIL was the simplest, fastest solution to make CPython thread-safe.
Impact on Multi-Threading:
How to Achieve True Parallelism:
To utilize multiple CPU cores for heavy calculations, use the 'multiprocessing' module (which spawns separate OS processes, each with its own memory space and GIL) or Python 3.13+ Free-Threading / GIL-less mode ('--disable-gil').
import time
from threading import Thread
from multiprocessing import Process
def heavy_countdown(n):
while n > 0:
n -= 1
# 1. Multi-Threading (2 Threads running on 1 Core due to GIL!)
start = time.time()
t1 = Thread(target=heavy_countdown, args=(50_000_000,))
t2 = Thread(target=heavy_countdown, args=(50_000_000,))
t1.start(); t2.start()
t1.join(); t2.join()
print('Threading Time:', round(time.time() - start, 2), 'sec')
# 2. Multiprocessing (2 Processes running in parallel on 2 CPU cores!)
start = time.time()
p1 = Process(target=heavy_countdown, args=(50_000_000,))
p2 = Process(target=heavy_countdown, args=(50_000_000,))
p1.start(); p2.start()
p1.join(); p2.join()
print('Multiprocessing Time:', round(time.time() - start, 2), 'sec')The GIL limits Python threads to 1 CPU core. Use threading for I/O-bound tasks and multiprocessing for CPU-bound tasks.