上一篇说过将在这一篇讨论下 多线程(Threading)和多进程(Multithreading)的区别

在此之前首先你要知道什么是GIL锁

GIL锁

GIL(Global Interpreter Lock 全局解释器锁),这是目前占统治地位的python解释器CPython中为了保证数据安全所实现的一种锁。不管进程中有多少线程,只有拿到了GIL锁的线程才可以在CPU上运行,即便是多核处理器。对一个进程而言,不管有多少线程,任一时刻,只会有一个线程在执行。对于CPU密集型的线程,其效率不仅仅不高,反而有可能比较低。python多线程比较适用于IO密集型的程序。对于需要并行运行的程序,或者程序瓶颈在于CPU单核的程序,可以考虑使用多进程。

官方的解释

The mechanism used by the CPython interpreter to assure that only one thread executes Python bytecode at a time. This simplifies the CPython implementation by making the object model (including critical built-in types such as dict) implicitly safe against concurrent access. Locking the entire interpreter makes it easier for the interpreter to be multi-threaded, at the expense of much of the parallelism afforded by multi-processor machines.

Python代码的执行由Python 虚拟机(也叫解释器主循环,CPython版本)来控制,Python 在设计之初就考虑到要在解释器的主循环中,同时只有一个线程在执行,即在任意时刻,只有一个线程在解释器中运行。对Python 虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。(没错,因为GIL锁,你一直用threading的多线程是假的,它一直由一个核心负责,当然对IO密集型的程序没有什么影响。)

针对GIL造成的性能问题:

  1. 使用更高版本的Python(高版本的Python对GIL进行了优化)
  2. 使用Multithreading替换Threading(多进程之间没有GIL)
  3. 使用Jython、IronPython等没有GIL的解释器
  4. 在对多核要求不高的情况下才使用Threading
  5. 使用协程(高效的单线程模式,也称微线程;通常与多进程配合使用)
  6. 将关键组件用C/C++编写为Python扩展,通过ctypes使Python程序直接调用C语言编译的动态链接库的导出函数。(with nogil调出GIL限制)

Python中threading和multithreading的区别(有GIL前提下)

threading是多线程库。线程都是运行在一个进程上,线程间共享数据容易,但是在多核CPU运行时并没有真正并行运行,单核无影响。

multithreading则是多进程库。多个进程运行,多进程能够让程序绕过GIL锁,去并行地处理程序,并能够更充分地使用(榨干)cpu。虽然它与threading模块本质不同,但是语法上非常相似。多进程库会为每个进程提供各自的解释器和GIL锁。

总结

  1. 一个进程包含多个线程
  2. 不同进程间数据很难共享,但同一进程中的数据共享较容易
  3. 进程间不会相互影响,但线程挂掉将导致整个进程挂掉
  4. 进程使用的内存地址可以限定使用量
  5. 进程要比线程消耗更多的资源
  6. 程序的瓶颈不在CPU或是IO密集型程序 建议还是使用threading,CPU密集型使用multithreading
最后修改:2022 年 05 月 18 日
如果觉得我的文章对你有用,请随意赞赏