The Python GIL: One Thread at a Time

The Python Global Interpreter Lock (GIL) is a mutex ensuring only one thread executes Python bytecode at a time. This serializes CPU-bound threads, but the lock is released during I/O, making it effective for network-bound tasks.
WHY IT EXISTS: CPython's memory management is not inherently thread-safe. To prevent race conditions and memory corruption from multiple threads modifying Python objects simultaneously, the GIL was introduced. It acts as a single, global lock, which was a simpler and more performant solution for single-threaded programs than adding complex, fine-grained locks to every data structure.
THE MENTAL MODEL: Imagine the Python interpreter is a small room with a single microphone (the GIL). No matter how many people (threads) are in the room, only the person holding the microphone can speak (execute Python bytecode). If a speaker needs to wait for a delivery from outside (an I/O operation), they put down the microphone, allowing someone else to pick it up and speak.
HOW IT WORKS: The GIL is a mutex that a thread must acquire before it can execute Python bytecode. The interpreter forces the running thread to release the GIL periodically, such as after a fixed number of instructions or when the thread blocks on an I/O operation like reading a file or making a network call. This allows other threads to run, creating concurrency but not true parallelism, as only one thread executes at any given instant.
WHEN TO USE IT: Despite the GIL, Python's threading module is highly effective for I/O-bound applications. If your program spends most of its time waiting for network responses, database queries, or disk access, threads are ideal. While one thread is blocked waiting for I/O, the GIL is released, and another thread can run, significantly improving application throughput.
WHEN NOT TO USE IT: Do not use the threading module for CPU-bound tasks if your goal is to reduce computation time by using multiple cores. Heavy numerical calculations, data compression, or image processing will not see a speedup. The GIL ensures only one thread's Python code runs at a time, creating a performance bottleneck. For these scenarios, use the multiprocessing module, which spawns separate processes, each with its own interpreter and memory space, thus bypassing the GIL.
ONE CANONICAL EXAMPLE: A web server built with FastAPI or Flask handling concurrent user requests. When one request handler thread is blocked waiting for a database query to complete (an I/O operation), the GIL is released. The server can then switch to another thread to process a different incoming request, achieving high concurrency for an I/O-bound workload.
Read the original → docs.python.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.