为了解决解释器/编译器里面的资源竞争问题.CPython
GIL对多线程的影响:
对CPython产生的多线程有影响,影响是:同一时刻只有一个线程能够运行,其他线程都在申请GIL
互斥锁:Python代码层面的
GIL:CPython层面的解释器锁 Global Inter... Lock
C语言写的存在内存管理的问题,就是自己要去申请创建内存和销毁内存空间.
C语言的资源管理不能让多个线程同时操作.
因为每个线程都会去获取全局资源,为了避免竞争出问题,才加GIL锁.
什么时候需要申请?
如果线程需要运行,申请全局资源
作用:锁定解释器内部的全局系统资源,比如内存,主要原因在于:C语言不允许多个线程同时操作系统资源<主要是内存>
GIL:只存在于CPython解释器中.
GIL释放机制:
1.>超时释放
2.>手动释放<线程退出>
3.>线程阻塞,自动释放
影响:
只对Cpython解释器产生的多线程程序中 ,导致产生的多线程中只能有一个线程执行.
不会影响多线程网络爬取数据<因为会有线程阻塞 情况下自动释放>,比单线程爬取有提升<在等待的时候切换>
只是一个历史遗留问题.
GIL和Python语言没关系,只是和解释器<CPython>有关系.
忽略GIL/如何避免这个GIL锁?
1.>使用单线程
2.>不使用Cpython解释器
3.>使用多进程
4.>换个语言,比如C语言写完以后编译的二进制代码,<C语言生成的动态库>直接让Python去调用这些二进制代码.
问题:有了GIL,用户层面是否不再需要加互斥锁?
注意:GIL和互斥锁不是同一个层面的概念,所以即使底层有GIL,但是Python语言层面的互斥锁仍然需要.
原因:因为我们无法控制底层GIL什么时候释放
GIL面试题:
1.>描述Python GIL的概念, 以及它对python多线程的影响?编写一个多线程抓取网页的程序,并阐明多线程抓取程序是否可比单线程性能有提升,并解释原因。
Python语言和GIL没有半毛钱关系。仅仅是由于历史原因在CPython虚拟机(解释器),难以移除GIL。
GIL:全局解释器锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。
2.>线程释放GIL锁的情况?
在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL
Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100
Python使用多进程是可以利用多核的CPU资源的。
3.>举例说明:
多线程爬取比单线程性能有提升,因为遇到IO阻塞会自动释放GIL锁
严重问题: 既然CPython解释存在GIL是否意味每个线程在全局变量就不用加Lock互斥锁了呢? 这是一个严重错误的想法,
为什么用户操作全局数据还需要加Lock,因为GIL的释放时机我们无法控制--操作可能并没有完成,而不像Lock那样我们用完才释放(操作完整)。
# ----------------------示例:处理GIL:单线程死循环-------------------------> # 占满一个CPU Ubuntu中使用 htop命令 查看CPU使用情况 while True: pass # -------------------------多线程死循环----------------------------------> # 无法使用多核CPU,没有占满2个CPU # --------------------------多进程---------------------------------------> # 两个进程占满了2个CPU # -------------------------C语言写,Python调用-----------------------------> # 占满了2个CPU # Cpython/jython/pypy<Python写的>