移除GIL非常困难,让我们去购物吧!(译者注:XXX is hard. Let's go shopping!在英语中类似于中文的咆哮体。其隐含意思为想成功完成某件事情非常困难,我们去直接寻找第三方的产品替代吧。) 不过,“free threading”这个补丁是有启发性意义的,其证明了一个关于Python解释器的基本要点:移除GIL是非常困难的。由于该补丁发布时所处的年代,解释器变得依赖更多的全局状态,这使得想要移除当今的GIL变得更加困难。值得一提的是,也正是因为这个原因,许多人对于尝试移除GIL变得更加有兴趣。困难的问题往往很有趣。 但是这可能有点被误导了。让我们考虑一下:如果我们有了一个神奇的补丁,其移除了GIL,并且没有对单线程的Python代码产生性能上的下降,那么什么事情将会发生?我们将会获得我们一直想要的:一个线程API可能会同时利用所有的处理器。那么现在,我们已经获得了我们希望的,但这确实是一个好事吗? 基于线程的编程毫无疑问是困难的。每当某个人觉得他了解关于线程是如何工作的一切的时候,总是会悄无声息的出现一些新的问题。因为在这方面想要得到正确合理的一致性真的是太难了,因此有一些非常知名的语言设计者和研究者已经总结得出了一些线程模型。就像某个写过多线程应用的人可以告诉你的一样,不管是多线程应用的开发还是调试都会比单线程的应用难上数倍。程序员通常所具有的顺序执行的思维模恰恰就是与并行执行模式不相匹配。GIL的出现无意中帮助了开发者免于陷入困境。在使用多线程时仍然需要同步原语的情况下,GIL事实上帮助我们保持不同线程之间的数据一致性问题。 那么现在看起来讨论Python最难得问题是有点问错了问题。我们有非常好的理由来说明为什么Python专家推荐我们使用多进程代替多线程,而不是去试图隐藏Python线程实现的不足。更进一步,我们鼓励开发者使用更安全更直接的方式实现并发模型,同时保留使用多线程进行开发除非你觉的真的非常必要的话。对于大多数人来说什么是最好的并行编程模型可能并不是十分清楚。但是目前我们清楚的是多线程的方式可能并不是最好的。 至于GIL,不要认为它在那的存在就是静态的和未经分析过的。Antoine Pitrou 在Python 3.2中实现了一个新的GIL,并且带着一些积极的结果。这是自1992年以来,GIL的一次最主要改变。这个改变非常巨大,很难在这里解释清楚,但是从一个更高层次的角度来说,旧的GIL通过对Python指令进行计数来确定何时放弃GIL。这样做的结果就是,单条Python指令将会包含大量的工作,即它们并没有被1:1的翻译成机器指令。在新的GIL实现中,用一个固定的超时时间来指示当前的线程以放弃这个锁。在当前线程保持这个锁,且当第二个线程请求这个锁的时候,当前线程就会在5ms后被强制释放掉这个锁(这就是说,当前线程每5ms就要检查其是否需要释放这个锁)。当任务是可行的时候,这会使得线程间的切换更加可预测。 然而,这并不是一个完美的改变。对于在各种类型的任务上有效利用GIL这个领域里,最活跃的研究者可能就是David Beazley了。除了对Python 3.2之前的GIL研究最深入,他还研究了这个最新的GIL实现,并且发现了很多有趣的程序方案。对于这些程序,即使是新的GIL实现,其表现也相当糟糕。他目前仍然通过一些实际的研究和发布一些实验结果来引领并推进着有关GIL的讨论。 不管某一个人对Python的GIL感觉如何,它仍然是Python语言里最困难的技术挑战。想要理解它的实现需要对操作系统设计、多线程编程、C语言、解释器设计和CPython解释器的实现有着非常彻底的理解。单是这些所需准备的就妨碍了很多开发者去更彻底的研究GIL。虽然如此,并没有迹象表明GIL在不久以后的任何一段时间内会远离我们。目前,它将继续给那些新接触Python,并且与此同时又对解决非常困难的技术问题感兴趣的人带来困惑和惊喜。 以上内容是基于我目前对Python解释器所做出的研究而写。虽然我还希望写一些有关解释器的其它方面内容,但是没有任何一个比全局解释器锁(GIL)更为人所知。虽然我认为这里有些内容是不准确的,但是这些技术上的细节与CPython的很多资源条目是不同的。如果你发现了不准确的内容,请及时告知我,这样我就会尽快对其进行改正。 英文原文:Python's Hardest Problem参与翻译(3人): |