CPython和线程模块Lock()

时间:2016-03-31 11:55:30

标签: python-3.x python-multithreading cpython

由于CPython具有GIL,因此不允许任何线程同时执行python代码,因此在给定进程中似乎存在线程安全性。

python线程模块Lock ()的目的是什么?即使没有线程可以同时执行,Lock ()在CPython中仍会出现哪些同步问题?

1 个答案:

答案 0 :(得分:1)

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(func)模块调用dis),您就可以获得:

  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,并且存储的值将是不同的。