11-1 Python中的GIL

匿名 (未验证) 提交于 2019-12-02 22:51:30

GIL: global interpreter lock (cpython)
GIL控制的字节码的执行,锁控制的是Python代码

  1. 什么是字节码,怎么查看字节码?
#通过dis模块查看函数add的字节码 import dis def add(a):     a = a+1     return a print(dis.dis(add))  #运行结果   6           0 LOAD_FAST                0 (a)               2 LOAD_CONST               1 (1)               4 BINARY_ADD               6 STORE_FAST               0 (a)    7           8 LOAD_FAST                0 (a)              10 RETURN_VALUE

2.GIL作用
GIL使得同一时刻只有一个线程在一个cpu上执行字节码。保证字节码的执行是线程安全的

有了GIL是不是就是多线程安全的,不需要考虑线程间同步呢?
答案肯定不是的,因为GIL会在适当的时候释放的。举例说明

total=0 def add():     #1. dosomething1     #2. io操作     #3. dosomething3     global total     for i in range(1000000):         total +=1  def desc():     global total     for i in range(1000000):         total -=1  import threading thread1=threading.Thread(target=add) thread2=threading.Thread(target=desc) thread1.start() thread2.start()  thread1.join() thread2.join() print(total)  #运行结果:每次结果都不一样 

不是说有GIL吗? 为什么还会出现这种现象呢?
首先,了解GIL的知识点:

  • 对于有I/O操作的多线程,每次遇到I/O操作便会进行GIL锁的释放
  • 如果是纯计算的程序,没有I/O操作,解释器会根据sys.setcheckinterval的设置来自动进行线程间的切换,默认情况下每隔100个时钟(python的内部时钟,对应于解释器执行的指令)就会释放GIL锁从而轮换到其他线程的执行
以简单实例说明 # a是全部共享变量 def add1(a):     a += 1  def desc1(a):     a -= 1 import dis print(dis.dis(add1)) print(dis.dis(desc1))  #运行结果  51           0 LOAD_FAST                0 (a)               2 LOAD_CONST               1 (1)               4 INPLACE_ADD               6 STORE_FAST               0 (a)               8 LOAD_CONST               0 (None)              10 RETURN_VALUE   55           0 LOAD_FAST                0 (a)               2 LOAD_CONST               1 (1)               4 INPLACE_SUBTRACT               6 STORE_FAST               0 (a)               8 LOAD_CONST               0 (None)              10 RETURN_VALUE  # 使用伪代码来说明,考虑一种极端情况来解释 add1 """ 1. load a            # a=0, 切换线程到desc1 ① 2. load 1            # 1  ③ 3. +                 # 1  ⑤ 4. 赋值给a            # a=1 ⑦ """  desc1 """ 1. load a           # a=0, 切换为add1   ② 2. load 1           # 1 ④ 3. -                # -1 ⑥ 4. 赋值给a           # a=-1 ⑧ """  经过add1和desc1操作之后,a要不就是1或者-1.而不是结果0

总结:因为线程同步解决的是代码的线程安全性问题,而GIL解决的只是字节码的线程安全,概念不一样

文章来源: 11-1 Python中的GIL
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!