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


Posted in Python onJanuary 29, 2021

先看一道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锁。

到此这篇关于详解Python中的GIL(全局解释器锁)详解及解决GIL的几种方案的文章就介绍到这了,更多相关Python GIL全局解释器锁内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python中针对函数处理的特殊方法
Mar 06 Python
Python中的下划线详解
Jun 24 Python
django上传图片并生成缩略图方法示例
Dec 11 Python
python爬虫爬取淘宝商品信息(selenum+phontomjs)
Feb 24 Python
python下解压缩zip文件并删除文件的实例
Apr 24 Python
实例讲解python中的协程
Oct 08 Python
Python实现平行坐标图的两种方法小结
Jul 04 Python
python创建子类的方法分析
Nov 28 Python
Django后端发送小程序微信模板消息示例(服务通知)
Dec 17 Python
Pytorch数据拼接与拆分操作实现图解
Apr 30 Python
如何对python的字典进行排序
Jun 19 Python
基于Tensorflow读取MNIST数据集时网络超时的解决方式
Jun 22 Python
Python爬虫获取op.gg英雄联盟英雄对位胜率的源码
Jan 29 #Python
python中spy++的使用超详细教程
Jan 29 #Python
Python Selenium破解滑块验证码最新版(GEETEST95%以上通过率)
Jan 29 #Python
详解pycharm的python包opencv(cv2)无代码提示问题的解决
Jan 29 #Python
如何用python开发Zeroc Ice应用
Jan 29 #Python
详解Pymongo常用查询方法总结
Jan 29 #Python
Python3使用tesserocr识别字母数字验证码的实现
Jan 29 #Python
You might like
php中可能用来加密字符串的函数[base64_encode、urlencode、sha1]
2012/01/16 PHP
PHP抓屏函数实现屏幕快照代码分享
2014/01/02 PHP
php生成动态验证码gif图片
2015/10/19 PHP
在多个页面使用同一个HTML片段的代码
2011/03/04 Javascript
jquery实现html页面 div 假分页有原理有代码
2014/09/06 Javascript
JavaScript中setUTCFullYear()方法的使用简介
2015/06/12 Javascript
JavaScript如何禁止Backspace键
2015/12/02 Javascript
Bootstrap实现基于carousel.js框架的轮播图效果
2017/05/02 Javascript
JavaScript实现AOP详解(面向切面编程,装饰者模式)
2017/12/19 Javascript
SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题的解决方法
2018/01/09 Javascript
vue+springboot前后端分离实现单点登录跨域问题解决方法
2018/01/30 Javascript
基于cropper.js封装vue实现在线图片裁剪组件功能
2018/03/01 Javascript
利用chrome浏览器进行js调试并找出元素绑定的点击事件详解
2021/01/30 Javascript
JavaScript根据json生成html表格的示例代码
2018/10/24 Javascript
vue基于viewer实现的图片查看器功能
2019/04/12 Javascript
微信小程序实现录音时的麦克风动画效果实例
2019/05/18 Javascript
vue开发拖拽进度条滑动组件
2019/09/21 Javascript
vue实现一个6个输入框的验证码输入组件功能的实例代码
2020/06/29 Javascript
[02:10]DOTA2 TI10勇士令状玩法及不朽Ⅰ展示:焕新世界,如你所期
2020/05/29 DOTA
Python解释执行原理分析
2014/08/22 Python
老生常谈Python进阶之装饰器
2017/05/11 Python
判断python字典中key是否存在的两种方法
2018/08/10 Python
Python使用pandas和xlsxwriter读写xlsx文件的方法示例
2019/04/09 Python
python中append实例用法总结
2019/07/30 Python
如何利用python给图片添加半透明水印
2019/09/06 Python
面向对象学习之pygame坦克大战
2019/09/11 Python
python标准库os库的函数介绍
2020/02/12 Python
python 中的9个实用技巧,助你提高开发效率
2020/08/30 Python
如何使用Python进行PDF图片识别OCR
2021/01/22 Python
浅析与CSS3的loading动画加载相关的transition优化
2015/05/18 HTML / CSS
利用CSS3制作简单的3d半透明立方体图片展示
2017/03/25 HTML / CSS
师范应届生求职信
2013/11/15 职场文书
领导班子整改方案和个人整改措施
2014/10/25 职场文书
大学生操行评语大全
2014/12/31 职场文书
给病人的慰问信
2015/03/23 职场文书
Win11 Dev 预览版25174.1000发布 (附更新修复内容汇总)
2022/08/05 数码科技