GIL & Threading
Overview
Python's biggest architectural quirk is the Global Interpreter Lock (GIL). The GIL is a mutex that ensures only ONE thread can execute Python bytecode at any given moment, preventing race conditions in memory management. Because of the GIL, standard multithreading does absolutely nothing to speed up CPU-heavy tasks (like math algorithms). However, the GIL is released during I/O operations (like network requests or file reading). Thus, Threading in Python is strictly for I/O-bound concurrency.
Syntax
import threading
import time
def fetch_data(server_id):
# Simulates a slow network request. The GIL is released here!
time.sleep(2)
print(f"Data fetched from Server {server_id}")
# These threads will execute concurrently, taking ~2 seconds total
# instead of 4 seconds sequentially.
t1 = threading.Thread(target=fetch_data, args=(1,))
t2 = threading.Thread(target=fetch_data, args=(2,))
t1.start()
t2.start()
# .join() pauses the main program until the threads finish
t1.join()
t2.join()Common Pitfalls
- Using the
threadingmodule to parallelize math or data processing. Due to the GIL, they will fight for lock access and actually run SLOWER than a single thread. Use themultiprocessingmodule for CPU math. - Race conditions. If two threads modify the same global variable simultaneously, data corruption occurs. You must use
threading.Lock()to protect critical sections.
Interview Questions
By abandoning threads and using the multiprocessing module. It spawns entirely separate OS-level processes, each with its own independent Python interpreter, memory space, and GIL, enabling true parallel execution across multiple CPU cores.
Real-World Example
Using ThreadPoolExecutor for modern, clean concurrency without manually managing thread objects.
from concurrent.futures import ThreadPoolExecutor
urls = ["url1.com", "url2.com", "url3.com"]
def download(url):
pass # HTTP request logic here
# Automatically provisions threads and maps the function to the data
with ThreadPoolExecutor(max_workers=5) as executor:
results = list(executor.map(download, urls))Check Your Knowledge
Test your understanding of GIL & Threading with these quick questions.