详解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网络编程学习笔记(八):XML生成与解析(DOM、ElementTree)
Jun 09 Python
Python 抓取动态网页内容方案详解
Dec 25 Python
python根据出生年份简单计算生肖的方法
Mar 27 Python
python简单的函数定义和用法实例
May 07 Python
实例讲解Python设计模式编程之工厂方法模式的使用
Mar 02 Python
python出现"IndentationError: unexpected indent"错误解决办法
Oct 15 Python
Python使用pickle模块存储数据报错解决示例代码
Jan 26 Python
numpy 进行数组拼接,分别在行和列上合并的实例
May 08 Python
实例介绍Python中整型
Feb 11 Python
Python GUI编程 文本弹窗的实例
Jun 11 Python
python如何解析配置文件并应用到项目中
Jun 27 Python
jenkins+python自动化测试持续集成教程
May 12 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 getName()函数讲解
2019/02/03 PHP
MSN消息提示类
2006/09/05 Javascript
JS在IE下缺少标识符的错误
2014/07/23 Javascript
Egret引擎开发指南之发布项目
2014/09/03 Javascript
javascript使用appendChild追加节点实例
2015/01/12 Javascript
Jquery实现地铁线路指示灯提示牌效果的方法
2015/03/02 Javascript
JQuery CheckBox(复选框)操作方法汇总
2015/04/15 Javascript
JavaScript实现同时调用多个函数的方法
2015/11/09 Javascript
Zero Clipboard实现浏览器复制到剪贴板的方法(多个复制按钮)
2016/03/24 Javascript
js实现可控制左右方向的无缝滚动效果
2016/05/29 Javascript
JavaScript必看小技巧(必看)
2016/06/07 Javascript
react-native使用react-navigation进行页面跳转导航的示例
2017/09/07 Javascript
详解JSONObject和JSONArray区别及基本用法
2017/10/25 Javascript
JS改变页面颜色源码分享
2018/02/24 Javascript
监听element-ui table滚动事件的方法
2019/03/26 Javascript
在NodeJs中使用node-schedule增加定时器任务的方法
2020/06/08 NodeJs
手把手教你实现 Promise的使用方法
2020/09/02 Javascript
在Python中使用SimpleParse模块进行解析的教程
2015/04/11 Python
python 实现将字典dict、列表list中的中文正常显示方法
2018/07/06 Python
利用Python进行图像的加法,图像混合(附代码)
2019/07/14 Python
详谈tensorflow gfile文件的用法
2020/02/05 Python
使用ITK-SNAP进行抠图操作并保存mask的实例
2020/07/01 Python
清洁工岗位职责
2014/01/29 职场文书
企业精细化管理实施方案
2014/03/23 职场文书
学生鉴定评语大全
2014/05/05 职场文书
媒矿安全生产承诺书
2014/05/23 职场文书
村党支部公开承诺书
2014/05/29 职场文书
副总经理任命书
2014/06/05 职场文书
歌剧魅影观后感
2015/06/05 职场文书
团支部组织委员竞选稿
2015/11/21 职场文书
2019新员工心得体会
2019/06/25 职场文书
工作总结之小学教师体育工作范文(3篇)
2019/10/07 职场文书
《攀登者》:“海拔8000米以上,你不能指望任何人”
2019/11/25 职场文书
pytorch中的model=model.to(device)使用说明
2021/05/24 Python
Python借助with语句实现代码段只执行有限次
2022/03/23 Python
SpringBoot详解自定义Stater的应用
2022/07/15 Java/Android