【发布时间】:2016-07-19 20:51:49
【问题描述】:
由于 CPython 有 GIL,不允许线程同时执行 python 代码,因此在给定进程中似乎存在线程安全。
那么python线程模块Lock ()的目的是什么?即使没有线程可以同时执行,Lock () 帮助解决的 CPython 中仍然会出现哪些同步问题?
【问题讨论】:
标签: python-3.x python-multithreading cpython
由于 CPython 有 GIL,不允许线程同时执行 python 代码,因此在给定进程中似乎存在线程安全。
那么python线程模块Lock ()的目的是什么?即使没有线程可以同时执行,Lock () 帮助解决的 CPython 中仍然会出现哪些同步问题?
【问题讨论】:
标签: python-3.x python-multithreading cpython
GIL 只确保一次只能运行一个线程。一个线程仍然有可能在指令之间被中断,而另一个线程有机会运行。因此,如果两个线程访问共享资源,则需要使用锁来保护访问。
我们来看这个例子:
from threading import Thread
i = 0
def func():
global i
while i < 1000000:
i += 1
if i != i:
print("i was modified")
for _ in range(10):
Thread(target=func).start()
虽然看起来if 条件不可能为真,但您很有可能会看到打印的行。怎么可能?
如果你查看func 的反汇编字节码(通过从dis 模块调用dis.dis(func)),你会得到:
7 0 SETUP_LOOP 51 (to 54)
>> 3 LOAD_GLOBAL 0 (i)
6 LOAD_CONST 1 (1000000)
9 COMPARE_OP 0 (<)
12 POP_JUMP_IF_FALSE 53
8 15 LOAD_GLOBAL 0 (i)
18 LOAD_CONST 2 (1)
21 INPLACE_ADD
22 STORE_GLOBAL 0 (i)
9 25 LOAD_GLOBAL 0 (i)
28 LOAD_GLOBAL 0 (i)
31 COMPARE_OP 3 (!=)
34 POP_JUMP_IF_FALSE 3
10 37 LOAD_GLOBAL 1 (print)
40 LOAD_CONST 3 ('i was modified')
43 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
46 POP_TOP
47 JUMP_ABSOLUTE 3
50 JUMP_ABSOLUTE 3
>> 53 POP_BLOCK
>> 54 LOAD_CONST 0 (None)
57 RETURN_VALUE
相关的指令是25和28。如果线程在这两个指令之间被中断,另一个therad可以修改全局变量i,存储的值会不同。
【讨论】: