详解Python中的GIL(全局解释器锁)详解及解决GIL的几种方案

作者:托尼stark 时间:2021-02-01 03:36:05 

先看一道GIL面试题:

描述Python GIL的概念, 以及它对python多线程的影响?编写一个多线程抓取网页的程序,并阐明多线程抓取程序是否可比单线程性能有提升,并解释原因。

GIL:又叫全局解释器锁,每个线程在执行的过程中都需要先获取GIL,保证同一时刻只有一个线程在运行,目的是解决多线程同时竞争程序中的全局变量而出现的线程安全问题。它并不是python语言的特性,仅仅是由于历史的原因在CPython解释器中难以移除,因为python语言运行环境大部分默认在CPython解释器中。

通过一个案例了解单线程和多线程的cpu占用率:

打开Ubuntu终端命令:输入htop,回车,红色箭头指向的2代表此时我的虚拟机中CPU有两个核心数

详解Python中的GIL(全局解释器锁)详解及解决GIL的几种方案

下面通过一个案例了解单线程死循环和多线程死循环的CPU占用率:

单线程死循环.py: 


#coding=utf-8
while True:
 pass

运行该程序,出现以下界面:

详解Python中的GIL(全局解释器锁)详解及解决GIL的几种方案

此时新开一个窗口,输入htop,查看CPU占用率,其中一个CPU占用率几乎为100%:

详解Python中的GIL(全局解释器锁)详解及解决GIL的几种方案

两个线程死循环.py


#coding=utf-8
import threading

#子线程死循环
def test():
 while True:
   pass

t1=threading.Thread(target=test)
t1.start()

#主线程死循环,
while True:
 pass

此时新开一个终端,输入htop查看CPU占用率,可以看到两个CPU任何一个并没有全部占满,而是交替执行的:

详解Python中的GIL(全局解释器锁)详解及解决GIL的几种方案

 这也就验证了多线程下每个线程在执行的过程中都需要先获取GIL,保证同一时刻只有一个线程在运行。

由于GIL的存在,即使是多线程,事实上同一时刻只能保证一个线程在运行,既然这样多线程的运行效率不就和单线程一样了吗,那为什么还要使用多线程呢?

由于以前的电脑基本都是单核CPU,多线程和单线程几乎看不出差别,可是由于计算机的迅速发展,现在的电脑几乎都是多核CPU了,最少也是两个核心数的,这时差别就出来了:通过之前的案例我们已经知道,即使在多核CPU中,多线程同一时刻也只有一个线程在运行,这样不仅不能利用多核CPU的优势,反而由于每个线程在多个CPU上是交替执行的,导致在不同CPU上切换时造成资源的浪费,反而会更慢。即原因是一个进程只存在一把gil锁,当在执行多个线程时,内部会争抢gil锁,这会造成当某一个线程没有抢到锁的时候会让cpu等待,进而不能合理利用多核cpu资源。

例如在使用多线程抓取网页内容时,遇到IO阻塞时,正在执行的线程会暂时释放GIL锁,这时其它线程会利用这个空隙时间,执行自己的代码,因此多线程抓取比单线程抓取性能要好。

说到在这里要先介绍两个概念:计算密集型和IO密集型

计算密集型:要进行大量的数值计算,例如进行上亿的数字计算、计算圆周率、对视频进行高清解码等等。这种计算密集型任务虽然也可以用多任务完成,但是花费的主要时间在任务切换的时间,此时CPU执行任务的效率比较低。

IO密集型:涉及到网络请求(time.sleep())、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。

解决GIL问题的方案:

1.使用其它语言,例如C,Java

2.使用其它解释器,如java的解释器jython

3.使用多进程

线程释放GIL锁的情况:

1.在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL。

2.Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100。

GIL面试题参考答案:

  • Python语言和GIL没有什么关系。仅仅是由于历史原因在Cpython虚拟机(解释器),难以移除GIL。

  • GIL:全局解释器锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。

  • 线程释放GIL锁的情况: 在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100。

  • Python使用多进程是可以利用多核的CPU资源的。

  • 多线程爬取比单线程性能有提升,因为遇到IO阻塞会自动释放GIL锁。

来源:https://blog.csdn.net/qq_40808154/article/details/89398076

标签:Python,GIL,全局解释器锁
0
投稿

猜你喜欢

  • asp如何在ADO中客户端利用好缓存技术?

    2010-06-17 12:50:00
  • 淘宝搜索框研究报告

    2010-07-27 12:49:00
  • 使用FSO把文本信息导入数据库

    2007-09-27 20:20:00
  • 详细介绍Python的鸭子类型

    2023-07-14 10:28:17
  • python如何将图片生成视频MP4

    2023-10-19 09:25:37
  • 浅析阿里巴巴前端招聘考题

    2008-01-19 09:52:00
  • 管理员必读10个重要MySQL客户启动选项

    2008-06-07 16:57:00
  • 循环神经网络TextRNN实现情感短文本分类任务

    2021-12-14 04:24:26
  • 详解Python当中的字符串和编码

    2021-05-26 07:07:39
  • 教你用python实现自动回复QQ消息(不到60行)

    2021-05-17 06:19:20
  • Python使用arrow库优雅地处理时间数据详解

    2023-02-26 07:14:12
  • Python选课系统开发程序

    2023-07-21 00:25:03
  • mysql数据库中字符集乱码问题原因及解决

    2024-01-14 19:38:10
  • 在Yii框架中使用PHP模板引擎Twig的例子

    2023-11-14 11:30:30
  • PHP的PDO大对象(LOBs)

    2023-06-07 06:45:36
  • php下intval()和(int)转换使用与区别

    2023-06-11 14:09:54
  • Python计算多幅图像栅格值的平均值

    2021-03-28 01:41:05
  • 利用Javascript判断操作系统的类型实现不同操作系统下的兼容性

    2024-02-27 00:00:25
  • js鼠标按键事件和键盘按键事件用法实例汇总

    2024-04-17 10:04:29
  • 五个小窍门帮你写出更好的CSS代码

    2009-06-09 12:42:00
  • asp之家 网络编程 m.aspxhome.com