详解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数组的处理代码
Jan 04 Python
Python命令行参数解析模块optparse使用实例
Apr 13 Python
Python Socket编程详细介绍
Mar 23 Python
python 3.6 tkinter+urllib+json实现火车车次信息查询功能
Dec 20 Python
python中kmeans聚类实现代码
Feb 23 Python
Python 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
Mar 19 Python
详解基于django实现的webssh简单例子
Jul 17 Python
详解Django+uwsgi+Nginx上线最佳实战
Mar 14 Python
Python求解正态分布置信区间教程
Nov 20 Python
Python:二维列表下标互换方式(矩阵转置)
Dec 02 Python
Scrapy框架实现的登录网站操作示例
Feb 06 Python
Python读取pdf表格写入excel的方法
Jan 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 zend解密软件绿色版测试可用
2008/04/14 PHP
php通过PHPExcel导入Excel表格到MySQL数据库的简单实例
2016/10/29 PHP
详细解读php的命名空间(二)
2018/02/21 PHP
PHP实现数组转JSon和JSon转数组的方法示例
2018/06/14 PHP
CSS和Javascript简单复习资料
2010/06/29 Javascript
深入理解JavaScript系列(14) 作用域链介绍(Scope Chain)
2012/04/12 Javascript
不使用XMLHttpRequest实现异步加载 Iframe和script
2012/10/29 Javascript
Jquery在指定DIV加载HTML示例代码
2014/02/17 Javascript
面向切面编程(AOP)的理解
2015/05/01 Javascript
JS实现的另类手风琴效果网页内容切换代码
2015/09/08 Javascript
JavaScript原生xmlHttp与jquery的ajax方法json数据格式实例
2015/12/04 Javascript
js+html5实现的自由落体运动效果代码
2016/01/28 Javascript
自己动手制作基于jQuery的Web页面加载进度条插件
2016/06/03 Javascript
对Angular.js Controller如何进行单元测试
2016/10/25 Javascript
node.js 和HTML5开发本地桌面应用程序
2016/12/13 Javascript
ES6学习教程之Map的常用方法总结
2017/08/03 Javascript
Vue引入sass并配置全局变量的方法
2018/06/27 Javascript
mpvue跳转页面及注意事项
2018/08/03 Javascript
Vue 开发音乐播放器之歌手页右侧快速入口功能
2018/08/08 Javascript
cordova+vue+webapp使用html5获取地理位置的方法
2019/07/06 Javascript
详解JavaScript作用域 闭包
2020/07/29 Javascript
python基础教程之面向对象的一些概念
2014/08/29 Python
python通过配置文件共享全局变量的实例
2019/01/11 Python
Python使用修饰器进行异常日志记录操作示例
2019/03/19 Python
Django的用户模块与权限系统的示例代码
2019/07/24 Python
Django在admin后台集成TinyMCE富文本编辑器的例子
2019/08/09 Python
Python extract及contains方法代码实例
2020/09/11 Python
python pymysql库的常用操作
2020/10/16 Python
IE9对HTML5中部分属性不支持的原因分析
2014/10/15 HTML / CSS
HTML5高仿微信聊天、微信聊天表情|对话框|编辑器功能
2018/04/23 HTML / CSS
物业管理大学生个人的自我评价
2013/10/10 职场文书
《钱学森》听课反思
2014/03/01 职场文书
《花瓣飘香》教学反思
2014/04/15 职场文书
乡镇党员干部群众路线对照检查材料思想汇报
2014/09/28 职场文书
合作意向书范本
2019/04/17 职场文书
女性励志书籍推荐
2019/08/19 职场文书