[Python] GIL (Global Interpreter Lock)
In CPython, the GIL (Global Interpreter Lock) is a mutex that protects access to Python objects, preventing multiple threads from executing Python bytecodes at once. The GIL prevents race conditions and ensures thread safety. In short, this mutex is necessary mainly because CPython’s memory management is not thread-safe.
Cooperative Multitasking
When receive some requests which are blocking operations, it can release GIL voluntarily, and start processing another request, instead of waiting for a response.
Preemptive Multitasking
Python text is compiled into a simpler binary format called bytecode, then the Python interpreter reads the bytecode and executes the instructions in it one by one. While the interpreter steps through your bytecode it release GIL involuntarily, and start processing another request, instead of waiting for a response.
Thread safety
The thread can lose the GIL at any moment if the operation is not atomic, so it need to ensure the safety for thread.
- Atomic operation
There is no opportunity for other threads to have the GIL if the operation is atomic, because it is a single bytecode.
l = [2, 4, 3, 1]
def func():
l.sort()
# ByteCode
0 LOAD_GLOBAL 0 (lst)
2 LOAD_METHOD 1 (sort)
4 CALL_METHOD 0
- Nonatomic operation
The GIL might be released involuntarily during nonatomic operation, because it is not a single bytecode.
n = 0
def func():
n += 1
# ByteCode
0 LOAD_GLOBAL 0 (n)
2 LOAD_CONST 1 (1)
4 INPLACE_ADD
6 STORE_FAST 0 (n)
Despite the GIL, still need locks to protect shared mutable state.
n = 0
lock = threading.Lock()
def func():
with lock:
n += 1