图解|为什么Python多线程无法利用多核

来源:微信公众号:后端技术指南针
出处:;mid=2247485445 --tt-darkmode-bgcolor: #131313;">1.全局解释锁如题: Python的多线程为什么不能利用多核处理器?
全局解释器锁(Global Interpreter Lock)是计算机程序设计语言解释器用于同步线程的一种机制 , 它使得任何时刻仅有一个线程在执行 。
即便在多核处理器上 , 使用 GIL 的解释器也只允许同一时间执行一个线程 , 常见的使用 GIL 的解释器有CPython与Ruby MRI 。
可以看到GIL并不是Python独有的特性 , 是解释型语言处理多线程问题的一种机制而非语言特性 。
2.Python的解释器Python是一门解释器语言 , 代码通过解释器执行 , Python存在多种解释器 , 分别基于不同语言开发 , 每个解释器有不同的特点 。
Python程序的解释和执行过程简图:
图解|为什么Python多线程无法利用多核文章插图

  • CPython
CPython是主流版本的解释器 , 这个解释器是使用C语言编写的 , 也是使用最为广泛的解释器 , 可以方便地和C/C++的类库进行交互 , 因此也是最受关注的解释器 。
  • Jython
一种由java语言编写的python解释器 , 是将python编译成Java字节码然后执行的一种解释器 , 可以方便地和Java的类库进行交互 。
  • IronPython
将Python代码解释为.Net平台上运行的字节码进行执行 , 类似Jython解释器 , 可以方便的和.Net平台上的类库进行交互 。 IPython
在交互效果上有所增强 , 但执行过程和功能方面和CPython是一样的 。
  • PyPy
一种使用JIT(just-in-time)技术的编译器 , 专注于执行速度 , 对Python代码进行动态编译 , 从而提高Python的执行速度 。
PyPy在处理python代码的过程中 , 一小部分功能的处理和CPython的执行结果是有差异的 , 如果项目中要使用PyPy来进行执行效率的提升的话 , 一定要事先了解下PyPy和CPython的区别 。
3.CPython的线程不安全CPython的线程是操作系统的原生线程 , 在Linux的pthread完全由操作系统调度执行 。
pthread本身不是线程安全的 , 需要使用者通过锁来实现多线程的安全运行 , 因此CPython解释器下的Python实现多线程也必然存在线程不安全的问题 。
这就为GIL在多核时代的使用埋下了隐患 。
4.GIL产生背景和挑战Python是Guido van Rossum 在1989年发布的 , 那个时候计算机的主频还没有达到1G , 程序全部都是运行在单核计算机上面 , 直到2005年多核处理器才被Intel开发出来 。
Python各版本发布时间轴:
图解|为什么Python多线程无法利用多核文章插图
4.1 多核化对软件系统的冲击戈登·摩尔 1965 年预测 , 每个集成电路的元件数量每 18 到 24 个月就会翻一倍 , 它的适用性预计会持续到 2015-2020 年 。
图解|为什么Python多线程无法利用多核文章插图
摩尔定律未失效前软件系统可以单纯借助硬件的进步来获得性能的提升或者只需少量改进 , 就可以坐享性能飞跃 。
然而从 2005 年开始 , 时钟速率的增长和晶体管数量的增长已不再同步 。
由于处理器材料的物理性质限制 , 时钟速率已停止增长甚至下降 , 处理器制造商开始将更多执行单元核心封装到单个芯片中 。
这一趋势给应用程序开发和编程语言设计带来越来越大的压力 。
程序员和编程语言决策者不得不考虑如何快速适应多核硬件 , 来提高软件性能和编程语言的市场占有率 , Python也不例外受到冲击 。
4.2 多核化对CPython的冲击在单核时代 , 崇尚优美、清晰、简单的吉多.范罗苏姆选择在解释器层面实现了一把全局互斥锁 , 来保护Python对象从而实现对单核CPU的使用率 , 这种做法在单核时代很奏效 。
倘若在单核时未选择GIL , 那么开发者就需要自己实现任务的管理 , 这样做对于CPU的利用率提高无法做到极致 。
图为Python之父吉多.范罗苏姆:
图解|为什么Python多线程无法利用多核文章插图
但是随着多核时代的到来 , 高效地利用CPU 核心的有效方法就是使用并行性 , 多线程是充分实现并行的好方法 , 但是CPython的GIL却阻碍了对多核CPU的利用 。
4.3 痛并快乐着的GILCPython的GIL给使用者带来了便利 , 并且在GIL的基础上开发了许多重要的Package和语言功能 。
但是多核CPU的普适和其他语言对Python的冲击 , 让GIL显得原始而粗暴 , 无法有效利用多核处理器成为了弊端 。
5.多核时代GIL暴露的问题要搞清楚GIL对多线程程序的影响就要了解GIL的运行基本原理 。