根据 Python文档జజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజ append
在Python上的操作 list
是原子性的。同时加法运算也不是原子的。
i = i + 1
我知道Python GIL是在强制执行 append
操作是原子的。我的问题是,为什么GIL没有对加法操作执行同样的规定?
请看下面的代码。
In [24]: L = []
In [25]: def func1():
...: L.append(2)
...:
In [26]: i = 0
In [27]: def func2():
...: i = i + 2
...:
两个函数的字节码如下图所示。
In [28]: dis.dis(func1)
2 0 LOAD_GLOBAL 0 (L)
2 LOAD_METHOD 1 (append)
4 LOAD_CONST 1 (2)
6 CALL_METHOD 1
8 POP_TOP
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
In [29]: dis.dis(func2)
2 0 LOAD_FAST 0 (i)
2 LOAD_CONST 1 (2)
4 BINARY_ADD
6 STORE_FAST 0 (i)
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
Python 确保线程切换只发生在字节码指令之间。字节码指令的不同之处是什么,使得 append
操作是原子的?
因为 append
操作会对被追加的列表产生副作用,如果不是原子性的,它将没有任何语义的机会(而且很有可能甩掉核心)。相比之下,加法的过程要简单得多,而且也是换算的,所以在一个线程中做i+=1,在另一个线程中做i-=1,当硝烟散尽时,最终结果是一样的。