What is the GIL in CPython and when does it limit performance?
py-mid-001
Your answer
Answer as you would in a real interview — explain your thinking, not just the conclusion.
Model answer
The Global Interpreter Lock is a mutex in CPython that allows only one thread to execute Python bytecode at a time, regardless of CPU core count. CPU-bound multi-threaded Python therefore does not achieve true parallelism — adding threads to a pure-Python compute task often makes it slower due to context-switching overhead. The GIL does not affect I/O-bound code because threads release it while waiting on I/O. For CPU-bound parallelism, use multiprocessing (separate processes, each with its own GIL), or C-extension libraries like NumPy that release the GIL internally. asyncio sidesteps the GIL entirely for I/O-bound concurrency on a single thread.
Code example
import concurrent.futures
# CPU-bound: use ProcessPoolExecutor to bypass GIL
def cpu_work(n):
return sum(i * i for i in range(n))
with concurrent.futures.ProcessPoolExecutor() as pool:
results = list(pool.map(cpu_work, [10_000_000] * 4))
# I/O-bound: ThreadPoolExecutor is fine (GIL released during I/O)
import urllib.request
urls = ["https://example.com"] * 10
with concurrent.futures.ThreadPoolExecutor(max_workers=20) as pool:
futures = [pool.submit(urllib.request.urlopen, u) for u in urls]
responses = [f.result() for f in futures]
Follow-up
How would you structure a service that must handle both CPU-intensive image processing and high-concurrency HTTP requests?