面试官:你如何破解 Python 的 GIL 的?这才是完美的回答

1. GIL 是什么?

在讲如何破解 GIL 的时候,首先要和你达成一个共识,那就 Python 中由于有 GIL 的存在,使得 Python 中的多线程即使在有多核的机器上,在同一时刻也只有一个线程在跑。

因此有不少人说,Python 中的多线程是假的多线程。

这个说法,也对,也不对。

说不对,是因为 Python 的解释器有多种,CPython,pypy 等,而上面所说的 GIL 只存在于 CPython 解释器中,只要你换一种解释器, GIL 便不复存在。

说对,是因为在大多数人的认知中,说 Python 大部分都指的是 CPython。

说了那么多,那么 GIL 到底是什么呢?怎么会让 Python 的多线程这么多年都饱受诟病。

GIL ,全称是Global Interpreter Lock,也叫做全局解释器锁。

所有的 Python 线程都需要在解释器这个虚拟机中运行,而在运行之前都要先获取 GIL 这个锁,然后每执行 100 个字节码,解释器就自动释放GIL锁,让别的线程有机会执行。因此即使你有多个 CPU 核,多个线程在同一个 Python 虚拟机中也应该是交替执行的。

2. 解决 GIL 的方法

了解什么是 GIL 后,下一步面试官肯定要问,那你平时都是用什么方法解决 GIL 存在的问题呢?

第一,使用多进程

多个Python进程有各自独立的GIL锁,互不影响。

第二,使用其他 Python 解释器

换其他的 Python 解释器,比如 pypy

第三,仍然使用多线程

因为在 IO 密集型任务中,多线程的『鸡肋』影响不大

第四,使用 C 扩展模块

还有一种就是调用C语言的链接库

3. 如何选择方案?

至于是选择多线程还是多进程,是有一套已成的逻辑存在的,关键要分析你的程序的运行的时间主要花费在哪里。

对于 IO 密集型的程序来说,导致程序运行慢的瓶颈是 IO 的等待,真正会占用 CPU 时间片的并不多,因为对所有面向 I/O 的(会调用内建的操作系统C代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待 I/O 的时候运行。

这也意味着,对于 IO 密集型的程序来说,本来用在 cpu 上的时间就很少,使用并行的方式从 10ms 减少到 5ms,其实意义不大,当你用上多核在速度上也不会有太大帮助的时候,使用有点 『鸡肋』的多线程,也许是个不错的选择。

对于 计算密集型的程序来说,你的程序中有大量的计算任务需要占用大量的 CPU 时间,这时候 Python 的假多线程的问题就开始暴露出来了,若执意使用多线程,会导致某个核上非常繁忙而其他核却非常闲的 CPU 时间浪费,这时候上多进程是最佳选择。

聪明的你,现在应该也发现了一个 BUG,多进程不管在 IO 密集型和计算密集型的程序中都能表现良好,那为什么不直接干脆一点,一刀切全部使用多进程呢?

这是个非常好的问题,要回答这个问题,就不得了解一下多进程和多线程的区别?

  1. 线程不能脱离进程单独存在,一个进程里至少有一个线程
  2. 一个进程里的多个线程,可以共享全局变量,通信也比较简单,而多进程不行,需要借助 multiprocessing.Value将其传入各个子进程进行共享
  3. 创建新线程非常简单,而创建新进程就不一样了,它需要对父进程进行一次克隆,因此它会比线程更占用内存
  4. 一个线程可以控制和操作同一进程里的其他线程;但是进程只能操作子进程
  5. 在不设置守护线程的情况下,主线程退出后,子线程也会同时退出。而如果主进程退出了,不管有没有设置守护,该进程下的所有线程都会退出。但多进程就不一样了,当父进程退出后,若未主动关闭子进程,子进程可以单独存在,处于游离的状态,因此父进程应该最大限制的保护其稳定性。
  6. 可以创建非常多的线程,但进程数却不宜过多,在 IO 密集型的场景下会使用多进程,若该机器上有其他计算密集型的程序在跑,那么你在 IO密集型的程序中也使用多进程,会增加该任务对 CPU 的抢占能力,会直接影响到其他程序的性能。
  7. 在多个进程之间切换,和在一个进程里的多个线程间切换,开销是不一样的。

由上对比可以看出,若是可以非黑即白地明确你的程序到底是 IO 密集型还是 计算密集型,那么千万要注意在方案的选择,牢记这一原则:IO 密集型选多线程,计算密集型选多进程。

上面说的是,非黑即白地明确是哪种程序类型,那假如你的程序的界线并不是那么明显,既有大量 IO 型的,也有大量密集型的呢?

先跟你普及一个知识点,Python 的线程中一旦执行 C 代码,那么 GIL 会怎么释放开来。

因此你可以将你的那些计算密集型任务使用 C 语言来编写,然后把.so链接库内容加载到Python中,这样一来,就算你在多线程中的计算型任务,也可以利用多个核来跑多个线程的目的!

关于Python技术储备

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
在这里插入图片描述

二、Python必备开发工具

在这里插入图片描述

四、Python视频合集

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
在这里插入图片描述

五、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。在这里插入图片描述

六、Python练习题

检查学习结果。
在这里插入图片描述

七、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
在这里插入图片描述
在这里插入图片描述
这份完整版的Python全套学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

👉[[CSDN大礼包:《python安装包&全套学习资料》免费分享]]安全链接,放心点击

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值