目录

  • GIL全局解释器锁
    • 一、引入:
    • 二、GIL介绍
    • 三、GIL与Lock
    • 四、GIL与多线程
    • 总结

GIL全局解释器锁

一、引入:

首先要明白,GIL并不是Python的一个特性,其实在我们通常所称呼的Python解释器,其实是CPython解释器,因为大部分Python程序都是基于该解释器执行的,当然还有JPython解释器(基于Java编写的),而这个GIL则是CPython解释器的特性,而不是Python的特性。

GIL全称:Global Interpreter Lock,官方解释

In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

结论:在CPython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势

二、GIL介绍

GIL本质上也是一把互斥锁,既然是互斥锁,本质上都是将并发变成串行,以此来控制同一时间内共享数据只能被一个任务所修改,进而保证数据安全。

GIL达到的效果则是,同一时间内只有一个线程能够拿到GIL锁,拿到GIL锁后,该线程就可以使用解释器进行操作。

小例子说明GIL的小部分作用:

没有GIL锁的话,如果有两个线程,一个线程是给变量添加数据,另一个线程则是垃圾回收机制的线程,此时可能就会出现一个问题,一个线程在定义数据产生后,还没有来的及将该数据的内存地址绑定给变量,就被垃圾回收机制给回收了(因为检测到这个数据计数为0),由于都是同一进程下的线程,且还是并发执行的,如果真的是这样执行,将给我们的程序造成很大的隐患。

三、GIL与Lock

可以存在的疑惑,既然有了GIL锁来保证同一时间只能有一个线程运行,那还需要Lock锁干嘛?

首先,我们需要达成共识:锁的目的是为了保护共享的数据,同一时间只能有一个线程来修改共享的数据

然后,我们可以得出结论:保护不同的数据就应该加不同的锁。

最后,问题就很明朗了,GIL 与Lock是两把锁,保护的数据不一样,前者是解释器级别的(当然保护的就是解释器级别的数据,比如垃圾回收的数据),后者是保护用户自己开发的应用程序的数据,很明显GIL不负责这件事,只能用户自定义加锁处理,即Lock

GIL保护的是解释器级别的数据,保护用户自己的数据则需要自己加锁处理,如下图:
  
再来分析我们的疑问:

  1. 如果现在存在100个线程,那么其中某一个线程会抢到GIL锁,我们且称它为:线程1。
  2. 当线程1拿到GIL可以使用解释器后,线程1使用一个函数对全局变量count进行+1操作之前进行了互斥锁Lock。
  3. 而此时线程1还未执行完+1操作,线程2就把GIL锁给抢走了,此时线程2拿到这个GIL也想来执行这个+1操作,但执行这个函数时,发现有一个Lock未被释放,那它只能阻塞住,被释放GIL。
  4. 当线程1再次抢到这个GIL后,继续在上一次暂停的位置完成的+1操作,做完以后,再把Lock、GIL给释放掉。此后其它线程重复1、2、3、4步骤

保护不同的数据就需要加不同的锁

四、GIL与多线程

有了GIL的存在,同一时刻同一进程中只有一个线程被执行

创建进程开销大、而线程开销小,却无法利用多核优势,Python不行了?
要解决这个问题,我们需要在几个点上达成一致:

  1. cpu到底是用来做计算的,还是用来做I/O的?
  2. 多cpu,意味着可以有多个核并行完成计算,所以多核提升的是计算性能
  3. 每个cpu一旦遇到I/O阻塞,仍然需要等待,所以多核对I/O操作没什么用处

所以我们Python中,多线程是并发操作的,而多进程是可以做到并行操作的。

那么在Python里遇到I/O操作时,线程所用资源以及速度都会优于进程的。

而如果计算的话,多进程则更占据优势

代码示例:计算密集型,多进程效率更高

from multiprocessing import Process
from threading import Thread
import os, timedef work():res = 0for i in range(100000000):res *= iif __name__ == '__main__':l = []print(os.cpu_count())  # 本机为8核start = time.time()for i in range(4):p = Process(target=work)  # 多进程、耗时6s多# p = Thread(target=work)  # 多线程、耗时19s多l.append(p)p.start()for p in l:p.join()stop = time.time()print('run time is %s' % (stop - start))

代码示例:I/O密集型,模拟I/O操作等待时间,线程并发效率更高

from multiprocessing import Process
from threading import Thread
import os, timedef work():time.sleep(4)if __name__ == '__main__':l = []print(os.cpu_count())  # 本机为8核start = time.time()for i in range(4):# p = Process(target=work)  # 多进程、耗时4.1s左右p = Thread(target=work)  # 多线程、耗时4.005s左右l.append(p)p.start()for p in l:p.join()stop = time.time()print('run time is %s' % (stop - start))

因为开启进程的开销会远大于开启线程,而做这种I/O较多的操作,多线程会更具有优势

应用场景举例:

多线程用于IO密集型,如socket,爬虫,web
多进程用于计算密集型,如金融分析

总结

  1. 因为GIL的存在,只有IO较多场景下的多线程会得到较好的性能。
  2. 如果对并行计算性能较高的程序可以考虑把核心部分也成C模块,或者使用多进程实现。
  3. GIL在较长一段时间内将会继续存在,但是会不断对其进行改进。

技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请点赞 收藏+关注 子夜期待您的关注,谢谢支持!

Python GIL全局解释器锁相关推荐

  1. python GIL 全局解释器锁详解

    Python多线程另一个很重要的话题--GIL(Global Interpreter Lock,即全局解释器锁)鲜有人知,甚至连很多Python老司机都觉得GIL就是一个谜 一.一个不解之谜 耳听为虚 ...

  2. python GIL(全局解释器锁)

    python  C 解释器有一个叫GIL 的东西作用: 每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码. 所以在python中,如果对于CPU密集型任务,多线程是没有用的 ...

  3. python gil 解除_详解Python中的GIL(全局解释器锁)详解及解决GIL的几种方案

    先看一道GIL面试题: 描述Python GIL的概念, 以及它对python多线程的影响?编写一个多线程抓取网页的程序,并阐明多线程抓取程序是否可比单线程性能有提升,并解释原因. GIL:又叫全局解 ...

  4. Python中的GIL(全局解释器锁)

    1. GIL全称Global Interpreter Lock,每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码. 2.GIL的缺点 GIL使Python不能充分利用多核心 ...

  5. python基础--GIL全局解释器锁、Event事件、信号量、死锁、递归锁

    ps:python解释器有很多种,最常见的就是C python解释器 GIL全局解释器锁: GIL本质上是一把互斥锁:将并发变成串行,牺牲效率保证了数据的安全 用来阻止同一个进程下的多个线程的同时执行 ...

  6. 【Python爬虫学习笔记11】Queue线程安全队列和GIL全局解释器锁

    Queue线程安全队列 在Python多线程编程中,虽然threading模块为我们提供了Lock类和Condition类借助锁机制来处理线程并发执行,但在实际开发中使用加锁和释放锁仍是一个经常性的且 ...

  7. Python高级——GIL全局解释器锁问题

    GIL全局解释器锁 GIL全局解释器锁是cpython解释器内部的一把锁,和python中的lock锁不是一个层面. GIL产生的背景:在cpython解释内部运行多个线程的时候,每个线程都需要解释器 ...

  8. gil php,网络编程之多线程——GIL全局解释器锁

    网络编程之多线程--GIL全局解释器锁 一.引子 定义: In CPython, the global interpreter lock, or GIL, is a mutex that preven ...

  9. python GIL :全局解释器

    cpython 解释器中存在一个GIL(全局解释器锁),无论多少个线程.多少颗cpu 他的作用就是保证同一时刻只有一个线程可以执行代码,因此造成了我们使用多线程的时候无法实现并行. 因为有GIL的存在 ...

最新文章

  1. mysql存储、function、触发器等实例
  2. 使用面部标记提取和深度神经网络进行“昏昏欲睡”的检测
  3. java -Math类
  4. 通过rxjs的一个例子, 来学习SwitchMap的使用方法
  5. 初见akka-02:rpc框架
  6. 【“互联网+”大赛华为云赛道】GaussDB命题攻略:支持三种开发语言,轻松完成数据库缓冲池
  7. php创建多级目录函数,php创建多层(多级)目录的函数
  8. [javascript] Promise API
  9. Flink 在 B 站的多元化探索与实践
  10. python udp
  11. DC888 : worklist slovers
  12. 软件测试中的白盒测试的工具,软件测试人员该如何选择白盒测试工具?常用的白盒测试工具汇总...
  13. java说的tps pv是什么_你知道服务器PV、TPS、QPS是怎么计算出来的吗?
  14. 抖音python广告用的什么音乐_被抖音捧火的几首纯音乐,都是你们要的原版,太震撼人心!...
  15. 微信小程序简易评分样式
  16. 数据分析案例分析:日化公司社群营销场景,产品SKU,用户转化率,用户流转地图
  17. 连载 | Android之Camera1实现相机开发
  18. python服务器环境搭建_python服务器环境搭建(2)——安装相关软件
  19. 14年优质服务 海科融通进军P2P资金托管
  20. 求圆心角的度数c语言程序,圆心角度数怎么求

热门文章

  1. springboot启动加载流程
  2. wifi速率协商交互过程
  3. RISK-V品牌的中国化历程(上)
  4. 正好配资股票杠杆2021.5.14复盘记录
  5. 动态代理、CGlib、AOP
  6. Win10桌面图标怎么显示“我的电脑“,“网络“,“我的文档“,“控制面板“图标
  7. iphone如何查看dns延迟_购买二手iPhone,如何正确快速查看手机串号?避免被坑!...
  8. 保5年用10年,绿源磷酸铁锂电池高能量超安全!
  9. 懂车帝app是哪个公司
  10. 特发性震颤会危及生活吗 日常要注意什么