GIL的作用是,对于一个解释器,只能有一个thread在执行bytecode。所以任何时刻只有一条bytecode在被一个thread执行。Python的多线程并不是严格意义上的并行执行,GIL在bytecode层面上保证了thread safe,但是python多线程包里依然提供了加锁机制,这是为何?
假设有个操作,比如x += 1
,这个操作需要多个bytecodes操作,在执行这个操作的多条bytecodes期间,可能会发生thread切换,这样就出现了线程竞争的情况。
比如以下案例:
1 2 3 4 5 6 7 8 9 10 11 | >>> def f(): ... global num ... num += 1 ... >>> dis.dis(f) 3 0 LOAD_GLOBAL 0 (num) 3 LOAD_CONST 1 (1) 6 INPLACE_ADD 7 STORE_GLOBAL 0 (num) 10 LOAD_CONST 0 (None) 13 RETURN_VALUE |
分析以上可知,要实现num += 1
操作总共使用了4条bytecodes。GIL并不能保证此操作的原子性,在LOAD_GLOBAL
和STORE_GLOBAL
执行之间,有可能发生线程切换。