Python 的GIL与线程锁

2019-08-21  本文已影响0人  UULU

Python 程序是如何运行的?

  1. 将源码*.py 编译成字节码*.pyc
  2. 再由 Python 虚拟机逐行解释*.pyc成机器码,通知 CPU 执行

名词解释:

什么是 GIL?

Python 虚拟机默认使用的是 CPython 解释器(C 语言实现),CPython 使用了 GIL (Golbal Iterpreter Lock - 全局解释器锁),来确保同一时间只有一个线程运行,所以即使再多的线程也只能有效的使用一个 CPU。

为什么不删除 GIL?

实验证明,如果放弃 GIL,使用大量细粒度的锁代替,导致单线程性能下降至少 30%。所以说 GIL 在支持多线程的同时能把单线程的优势最大地发挥出来。

GIL 的限制

由于 GIL 的存在,即便是多线程的 Python 程序也无法利用多核 CPU 的优势。不过 I/O 密集型程序,依然适合使用多线程,因为它们大部分时间都在等待 I/O,对 CPU 依赖很低。

名词解释:

怎么充分的利用多核?

使用多进程替代多线程,或者使用 C 扩展

有了 GIL 还需要线程锁吗?

需要。GIL 只是解释器级别的锁,它能保证当多个线程在修改一个变量时不会崩溃,但结果可能是错乱的。

如多个线程修改全部变量i = i + 1,是先读取 i,再加 1 后,最后写回内存,这会把在读与写期间其他线程对 i 的所有修改覆都盖掉。所以我们需要用线程锁来对整个读写过程加锁。

PyPy 是什么?

Python 语言实现的另一种解释器,使用了 JIT 编译方式,没有 GIL。运行 Pure Python (纯 Python 代码) 程序速度更快。如果依赖了 C 扩展,反而会慢,如 MysqlDB、protobuf 库。

JIT 与其他编译方式的对比:

总结

根据应用场景选择最佳的性能优化方案

  1. I/O 密集型: 使用多线程
  2. I/O 密集型 & Pure Python: 使用 Pypy 解释器
  3. CPU 密集型: 使用多进程或把复杂逻辑用 C 扩展实现
上一篇 下一篇

猜你喜欢

热点阅读