关于python的GIL全局解释器锁的简单理解

GIL是解释器内部的一把锁,确切一点说是CPython解释器内部的一把锁,所以要注意区分 这和我们在Python代码中使用线程锁Lock并不是一个层面的概念。

1. GIL产生的背景:

在CPython解释内部运行多个线程的时候,每个线程都需要解释器内部申请相应的全局资源,由于C语言本身比较底层造成CPython在管理所有全局资源的时候并不能应对所有线程同时的资源请求,因此为了防止资源竞争而发生错误,对所有线程申请全局资源增加了限制-全局解释器锁。

言外之意,就是全局解释器就是为了锁定整个解释器内部的全局资源,每个线程想要运行首先获取GIL,而GIL本身又是一把互斥锁,造成所有线程只能一个一个one-by-one-并发-交替的执行。

2. GIL什么时候释放

  • 在当前线程执行超时后会自动释放
  • 在当前线程执行阻塞操作时会自动释放
  • 当前执行完成时

关于Guido龟叔的声明:http://www.artima.com/forums/flat.jsp?forum=106&thread=214235 

Python之父在观点的最后部分说明 the language doesn't require the GIL -- it's only the CPython virtual machine that has historically been unable to shed it.

解释来说就是Python语言和GIL没有半毛钱关系。仅仅是由于历史原因在Cpython虚拟机(解释器),难以移除GIL 

3. 严重问题: 既然CPython解释存在GIL是否意味每个线程在全局变量就不用加Lock互斥锁了呢?

这是一个严重错误的想法,为什么用户操作全局数据还需要加Lock,因为GIL的释放时机我们无法控制-操作非常可能并没有完成,而不像Lock那样我们用完才释放(操作完整)。

 正因为解释器锁的原因导致python的多线程说到底还是单线程,每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。所以就算使用多线程,其实还是一个线程在工作,但是由于在在IO操作等可能会引起阻塞,会暂时释放GIL,执行完毕后,再重新获取GIL,所以在进行IO等操作时的运行速度还是要比单线程速度快。

但是在运行计算密集型的程序时,需要使用CPU进行大量的计算,但由于GIL锁的性质导致程序巡行中始终都是一个CPU进行计算,所以计算速度及其缓慢,运行此类的程序不推荐使用线程,有两种方式解决:

  • 使用多进程的方式,避免GIL锁的约束
  • 使用其他运行速度较快的语言模块,例如C语言
posted @ 2018-10-01 16:19  Yeang  阅读(383)  评论(0编辑  收藏  举报