沙龙晃荡 | 去哪儿、陌陌、ThoughtWorks在主动化运维中的实践!10.28不见不散!
Python中因为应用了全局解释锁(GIL)的原因,代码并不克不及同时在多核上并发的运行,也就是说,Python的多线程不克不及并发,很多人会发明应用多线程来改进本身的Python代码后,法度榜样的运行效力却降低了。这篇文┞仿对Python中的全局解释锁(GIL)进行了介绍。作者认为这是Python中最令人头疼的问题。
十年多年来,Python 的全局说冥器锁(GIL)给新手和专家们带来了巨大年夜的挫折感亲睦奇心。

悬而未决的问题
这些问题很实用,它们的谜底也十分有趣。GIL 为很多对象的拜访供给这保护,比如当前哨程状况和为垃圾收受接收而用的堆分派对象。这对 Python 说话来说没什么奇怪的,它须要应用一个 GIL 。这是该实现的一种产品。如今也有不应用 GIL 的 Python 说冥器(和编译器)。然则对于 CPython 来说,大年夜其产生到如今 GIL 就一向在存在了。
每个范畴都邑有这么一个问题:它难度大年夜、耗时多,仅仅是测验测验解决这个问题都邑让人震动。全部社区在良久以前就放弃了这个问题,如今只有少数人在尽力试图解决它。对于初学者来说,解决如许高难度的问题,会给他带来足够的荣誉。计算机科学范畴中的 P = NP 就是如许的问题。如不雅能用多项式时光复杂度解决这个问题,那的确就可以改变世界了。Python 中最艰苦的问题比 P = NP 要轻易一些,不过迄今仍然没有一个知足的谜底,解决这个问题和解决 P = NP 问题一样具有概绫屈性。正因为如斯, Python 社区会有如斯多的人存眷于这个的问题: “对于全局说冥器锁(GIL)能做什么?”
我们如今能做什么呢?难道作为 Python 开辟人员的我们要放弃应用多线程来实现并行吗?为什么 GIL 在某一时刻只许可一个线程在运行呢?在并发拜访时,难道弗成以用粒度更细的锁来保护多个自力对象?为什么没有人做过类似的测验测验呢?
Python 的底层
要懂得 GIL 的含义,我们须要大年夜 Python 的基本说起。像 C++ 如许的说话属于编译型说话,顾名思义,该类型说话的代码输入到编译器,由编译器根据说话的语法进行解析,生成与说话无关的中心表示,最后链接成由高度优化的机械码构成的可履行法度榜样。因为编译器可以获取全部代码(或者是一大年夜段相对自力的代码),所以编译器可以对代码进行深度优化。这使得它可以对不合的说话构造之间的交互进行推理,大年夜而做出更有效的优化。
相反,Python 是解释型说话。代码被输入到说冥器来运行。说冥器在履行之前对代码一窍不通;它肮脏道 Python 的规矩,以及如安在履行过程中动态地应用这些规矩。它也有一些优化,然则和编译型说话的优化完全不合。因为说冥器不克不及很好地对代码进行推导,Python 的大年夜部分优化其实是说冥器本身的优化。更快的说冥器天然意味着更快的法度榜样运行速度,而这种优化对开辟者来说是免费的。也就是说,说冥器优化后,开辟者不消修改 Python 代码就可以坐享优化带来的好处。
这是异常重要的一点,这里有须要在强调一下。在一致前提下,Python 法度榜样的运行速度与说冥器的“速度”直接相干相干。无论开辟者如何优化本身的代码,法度榜样的履行速度照样受限于说冥器的履行效力。很明显,这就是为什么做了如斯多的工作却竽暌古化 Python 说冥器。这大年夜概是离 Python 开辟者比来的免费的午餐。
免费午餐停止了
照样没有停止?摩尔定律告诉了我们硬件提速的时光表,同时,整整一代法度榜样员学会了如安在摩尔定律下编写代码。如不雅法度榜样员写了比较慢的代码,最简单的办法平日是稍稍等待一下更快的处理器问世即可。事实上,摩尔定律仍然是并且会在很长一段时光内是有效的,不过它生效的方法有了根本的变更。时钟频率不会稳定增长到一个高弗成攀的速度,取而代之的是经由过程多菏攀来应用晶体管密度进步带来的好处。想要法度榜样可以或许充分应用新处理器的机能,就必须按照并发方法对代码进行重写。
大年夜部分开辟者听到“并发”平日会立时想到多线程法度榜样。今朝,多线程仍是应用多核体系最常见的方法。多线程编程比传统的“次序”编程要难很多,不过细心的法度榜样员可以在代码中充分应用多线程的并发性。既然几乎所有应用广泛的现代编程说话都支撑多线程编程,说话在多线程方面的实现应当是过后添加上去的。
那么在不合线程同时拜访数据时,如何才能保护数据呢?谜底是全局说冥器锁。顾名思义,这是一个加在说冥器上的全局锁(大年夜互斥量或者类似便义上来看)。这种方法是很安然,然则(对于 Python 初学者来说)这也就意味着:对于任何 Python 法度榜样,不论有若干线程,若干处理器,任何时刻都只有一个线程在履行。
不测的事实
如今我们来看一下问题的关键地点。想要应用多核体系,Python 必须支撑多线程。作为解释型说话,Python 的说冥器对多线程的支撑必须是既安然又高效的。我们都知道多线程编程带来的问题。说冥器必须避免不合的线迟疑作内部共享的数据。同时还要包管用户线程能完成尽量多的计算。
很多人都是有时发明这个事实。网上的评论辩论组和留言板充斥着来自 Python 初学者和专家提出的类似的问题:为什愦我全新的多线程 Python 法度榜样运行得比其只有一个线程的时刻还要慢?在问这个问题时,很多人还认为本身像个傻瓜,因为如不雅法度榜样确切是可并行的,那么两个线程的法度榜样显然要比单线程要快。事实上,问及这个问题的次数实袈溱太多了,Python 的专家们已经为它预备了一个标准谜底:不要应用多线程,请应用多过程。但这个谜底比问题本身加倍让仁攀困惑:难道我不克不及在 Python 中应用多线程?在 Python 如许风行的说话中应用多线程毕竟是有多糟糕,连专家都建议不要应用。是我哪琅绫腔有搞明白吗?
推荐阅读
沙龙晃荡 | 去哪儿、陌陌、ThoughtWorks在主动化运维中的实践!10.28不见不散! 一、一些概念 浅Copy:指针的复制,只是多了一个指向这块内存的指针,共用一块内存。 深Copy:内存的复>>>详细阅读
本文标题:最令人头疼的Python问题
地址:http://www.17bianji.com/lsqh/38077.html
1/2 1

网友点评
精彩导读
科技快报
品牌展示