震惊python是个“假的多线程”?!(秒懂GIL全局解释器锁)

Posted HUTEROX

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了震惊python是个“假的多线程”?!(秒懂GIL全局解释器锁)相关的知识,希望对你有一定的参考价值。

前言

本来我是不打算写这个玩意的,但是在B呼(Zhi呼)上看到有人对python的运行效率和线程运行大肆鄙夷,我觉得还是有必要出来仔细的澄清一下原由,解释一下python的多线程到底是怎么一回事,为什么说他是个“假的多线程”这样做对我们的python的多线程到底有多少影响,会对我们的运行效率有多大影响。做出一个客观全面的分析,以后可以回应那些“Java吹”,“贬python”(虽然我java我也在用,而且用起来也不错对我个人的提升也比较大,但是任何一款计算机语言都不是完美的,不应该存在鄙视链,有种都给爷爬C语言爬汇编去)
先说一下结论:
我们说到python一般指的是Cpython这个是官方推荐的,网上的大部分资源都是Cpython,基于C语言做的解释器。而问题也就出现在这里。只有Cpython的多线程才是“假的多线程”,原因是由于解释器自带了一个锁叫做(GIL global interpreter lock)。但是和其他的例如Java的多线程Cpython这种多线程的区别是,python只能使用单核,也就是是假如你的CPU是多核的,但是python的多线程只能使用一个核。换句话说这种线程能够并发,但是不能并行。要想并行只能通过换解释器(Jpython,pypython据说这玩意可以把python转化为静态语言在未来很有可能流行并且性能接近C),或者使用进程来解决问题。python的多线程适合IO密集型运算!

GIL锁

假设没有GIL的流程

我们先来看看一个python解释器的结构

通过上面的图其实也可以发现,Java这玩意其实也是个动态语言只是在编译上机制有些许区别,而且大部分情况下我们部署的项目运行的都是Java字节码,而python更多是作为脚本使用,一般是跑代码。
那么如果没有GIL的话,那么当有一个线程进入时,会通过解释器然后再由操作系统帮我们对CPU进行分配。

有GIL后

那么现在问题来了我们加了个锁

GIL的由来

这个时由于历史原因,由于最先诞生的C语言解释器的时代是个单核CPU的时代,所以为了节约时间成本等等原因,导致了Cpython解释器偷了个懒。那么为什么要加锁呢,这个锁其实是为了保护解释器自己的数据安全,说句大实话就是当时的程序员偷了个懒,没想到今天的硬件发展那么快。所以这个解释器适合单核CPU,之后由于这个锁加上操作系统的配合导致了它在进程当中开线程时只能使用一个内核

多线程的轮换机制

通过我们前面的解释器的示意图我们不难看出在实际当中我们的python多线程时如何工作的。
顺便解释一下什么是并行。

那么在python当中,由于只能使用一个核,那么在它开多个线程的时候就是这样的。
(运算密集型)

(IO密集型)
当我们的计算机进行IO处理时是不使用CPU的那么这个时候我们的线程就会切换(如果当前线程在IO处理时)(IO,文件存储,网络传输。。。)

总结

这个就是python多线程的问题所在了,当你使用单核CPU时运行图示和上面的差不多。所以问题就是python理论上它的多线程是真的,但是问题出在解释器上面。当前没有太好的办法解决这个问题,毕竟一个解释器的工程那么繁杂,而且还有很多前辈留下的坑,所以暂时时解决不了的。况且为什么一定要用Cpython,我们其实在我们专门的项目里面是可以使用pypython的只是这样做会带来兼容性问题。但是我相信pypython一定是个趋势,毕竟如果能够将python转化为静态语言运行的话,那么效率绝对比现在要高,而且这玩意号称性能接近C,所以说如果有人再拿运行效率说事,而不去考虑项目实际的情况,直接否定,那只能说那个程序员其实就是个垃圾在找存在感
https://doc.pypy.org/en/latest/install.html

以上是关于震惊python是个“假的多线程”?!(秒懂GIL全局解释器锁)的主要内容,如果未能解决你的问题,请参考以下文章

python多线程

这样学 Python 多线程与进程

了解ansible

关于GIL一点思考

多线程的使用

java 多线程 面试