首页 > 编程语言 >再谈Python多线程--避免GIL对性能的影响

再谈Python多线程--避免GIL对性能的影响

时间:2022-12-20 11:38:41浏览次数:46  
标签:解释器 多线程 Python 线程 GIL CPU


在Python中使用多线程,如果你对GIL本身没有一定的了解;那么很有可能你只是写出了正确的多线程代码,而并没有达到多线程的目的,甚至截然相反的效果。下面介绍了Python中GIL的作用和局限性,并提供了避免GIL影响性能的几个建议。

 

GIL是CPython中特有的全局解释器锁(其它实现版本因为有自己线程调度机制,所以没有GIL机制)。本质上讲它就是Python进程中的一把超大锁。这把锁在解释器进程中是全局有效的,它主要锁定Python线程的CPU执行资源。

 

换句话说,在CPython解释器中当一个线程需要执行CPU进行计算之前,它需要先获得这把大锁;否则即使已经被操作系统调度出来,但仍然无法执行计算。所以CPython解释器中,线程的想要执行CPU指令需要2个条件:

  1. 被操作系统调度出来【操作系统允许它占用CPU】
  2. 获取到GIL【CPython解释器允许它执行指令】

非常不幸的是,我们并不总是能满足这2个条件。经常出现的情况是:已经满足条件1,却被条件2限制。而这就是GIL影响Python性能的主要原因【其它语言只需满足条件1即可】。

如果Python(这里默认指CPython)在单核CPU的机器上执行,它的多线程与单线程、以及其它语言的多线程在本质上并没有什么不一样。【所有线程都是轮流占用CPU执行指令】

 

 

 

而如果Python在多核CPU机器上执行的时候,性能则会非常槽糕。主要原因是在单核的时候,同时只有一个线程在执行CPU,所以这个线程总是能获取到GIL。而换到多核的时候,同时会有多个线程在不同的CPU核心上执行,此时不同线程之间就需要竞争GIL,而GIL只能同时被一个线程申请到,所以会导致其它线程处于闲置状态【即使它已经拥有了CPU资源】。所以Python在多核CPU上的多线程始终只有单线程在跑程序。

 

在早期的Python版本(3.2之前)中,GIL除了会让多线程在多核机器下表现槽糕外,它还会导致某些线程场景占用GIL,而其它线程却无法申请到。典型场景是:

 

 

  • 在2个线程的情况下
  • 一个是IO密集型线程
  • 一个是计算密集型线程

 

 

那么最后的结果便是,一旦计算密集型线程获得了GIL,那么它在很长一段时间内都将占据GIL,甚至一直到该线程执行结束。因为计算密集型线程在释放GIL之后又会立即去申请GIL,并且通常在其它线程还没有调度完之前它就已经重新获取到了GIL。【因为GIL它没有锁通知机制,比如:Condition锁】

 

在Python3.4之后,由于对GIL有了较大的改进。在单核的情况下,对于单个线程长期占用GIL的情况有所好转;但是在多核的情况下,性能仍然还是没有多大的改善。
 

很多时候有些事情我们无法改变,但是生活给了我们智慧;所以为了客服困难,我们始终还是能找到解决办法的。虽然默认情况下GIL对Python多线程的多核的情况下有较大的性能影响,但是为了能在Python中利用多核来提高计算效率,还是有如下的方法可以实现的:

 

  • 使用python3.4或更高版本(对GIL机制进行了优化)
  • 使用多进程替换多线程(多进程之间没有GIL,但是进程本身的资源消耗较多)
  • 使用C编写高性能模块(with nogil调出GIL限制)
  • 指定cpu运行线程(使用affinity模块)
  • 使用Jython、IronPython等无GIL解释器
  • 全IO密集型任务时使用多线程
  • 使用协程(高效的单线程模式,也称微线程;通常与多进程配合使用)

 

关于GIL的实现原理、改进内容、适用场景等知识点,可以查看这里。更多关于学习Python的文章请关注下方二维码。

再谈Python多线程--避免GIL对性能的影响_gil

标签:解释器,多线程,Python,线程,GIL,CPU
From: https://blog.51cto.com/u_15918230/5954622

相关文章

  • Linux下安装python+appium+android(附带各种错误解决办法)
    文章目录​​安装AndroidSDK​​​​安装nodejs、NPM、cnpm​​​​安装Appium​​​​安装Python和基础库​​​​设置WIFI连接及调试​​​​引用​​​​安装错误解决​......
  • Python单元测试报告框架PyTestReport
    文章目录开局一张图安装通过pip安装通过安装包通过源码(最新版本)使用单元测试使用样例附录​​原文链接​​如果你是Java栈的同学,那么你可能知道extentreport测试报告框架。......
  • Python面试常见算法题集锦(递归部分)
    0x1前言开始学习python基础的时候,有以下几种算法是面试中常见的,也是前期学习python的时候可以连带学习了解的,不卡门槛哟0x2实现算法的方式很多种,而算法的实现也是分程......
  • python2.X编码问题梳理
    首先这些问题只有在python2.X版本出现,因为3.X版本中python环境就只有unicode类型的字符串了,即所有程序中处理的都会自动转换成unicode字符串。那么2.X......
  • python抓网页资源小脚本
    #!/usr/bin/envpython#coding:utf-8importurllibdeffilter_src(file_name):resource_list=[]f_obj=open(file_name)forf_lineinf_obj:if'......
  • python中的编解码攻略
    正如其他语言一样,在Python的世界里也有有字符的编解码问题;有的在命令行回显时出现,有的在读取文件时出现,有的在执行命令时出现,有的在读取数据库时出现,不尽相同。注:如未特别申......
  • python PIL图片简单处理
    #!/usr/bin/envpython#-*-coding:utf-8-*-fromPILimportImagef=r'1.jpg'defresize(fn,width=None,height=None):printfnim=Image.open(fn)......
  • python中telnetlib模块的使用
    python下能支持telnet的模块telnetlib是内置模块,直接import就可以了,其基本的使用方法也是比较简单的。 #encoding=utf-8defdo_telnet(Host,username,password,finish,......
  • python模块的打包
    模块安装:需要安装对应版本的setuptools模块,这是一个python的模块打包工具。(可以在pypi上找到)样例代码:新建test.py文件,内容如下:print"showme"新建一个setup.py编译文......
  • python 网站爬虫需要哪些技术?
    对于从事网络爬虫行业的资深技术员来说,正常只要学会下面几点,基本就能够独立完成爬虫任务。学Python爬虫需要学习的八个知识点:1、HTMLHTML被称为超文本标记语言,有着一系......