Python: GIL

GIL or Global Interpreter Lock is an implementation details of CPython. Reference counting is how CPython implements automatic garbage collection. With multiple threads, synchronization is required for correct reference counting. CPython takes a process-wide lock and that is GIL. Consequently, with CPython, for a single process, only one Python byte-code (by a thread) can execute at any point in time, even if there are more than one cores available on the CPU.

Asyncio in Python uses event loop concurrency model. The idea is to build a concurrent server without using multiple threads. The event loop runs on a single thread of a process and executes tasks from a queue. The event loop concurrency model is cooperative and it works only if care is taken to not block the thread that runs the event loop. If a task performs a CPU-heavy or blocking I/O operation, the event loop blocks, blocking the entire server.

For I/O operations, GIL is released (in kernel space of a system call), so using non-blocking I/O APIs available in the OS can unblock the event loop. If non-blocking I/O API is unavailable, executing that I/O operation with ThreadPoolExecutor can unblock the event loop.

For CPU bound operations, ProcessPoolExecutor is the way to go. Different processes have their own GIL, so the GIL of the process running the event loop will not be locked.

Leave a comment