GIL only requires the interpreter to fully execute one bytecode instruction before another thread can take over. However, there is no reason to assume that the increment operation is a single instruction. For instance:
>>> import dis >>> dis.dis(compile("x=753","","exec")) 1 0 LOAD_CONST 0 (753) 3 STORE_NAME 0 (x) 6 LOAD_CONST 1 (None) 9 RETURN_VALUE >>> dis.dis(compile("x+=1","","exec")) 1 0 LOAD_NAME 0 (x) 3 LOAD_CONST 0 (1) 6 INPLACE_ADD 7 STORE_NAME 0 (x) 10 LOAD_CONST 1 (None) 13 RETURN_VALUE
As you can see, even these simple operations are more than one bytecode command. Therefore, when sharing data between threads, you should use a separate locking mechanism (for example, threading.lock) to ensure data consistency.
source share