python多线程代码运行速度更慢-原因解析

   写出了正确的多线程代码,运行速度反而比单线程慢很多,原来是由于GIL(Global Interpreter Lock)!
GIL 是Cpython(Python语言的主流解释器)特有的全局解释器锁(其他解释器因为有自己的线程调度机制,所以没有GIL机制),GIL锁定Python线程中的CPU执行资源。线程在执行代码时,必须先获得这把锁,才获得CPU执行代码指令。如果这把锁被其他线程占用,该线程就只能等待,等到占有该锁的线程释放锁。
在Cpython解释器中,线程要想执行CPU指令需要2个条件:

被操作系统调度出来(操作系统允许它占用CPU)
获取到GIL(Cpython解释器允许它执行指令)
如果写出正确的多线程代码,执行的情况就是会有线程满足条件1不满足条件2,这时只能等待。
在单核CPU机器上,多线程与单线程在本质上并无不同,因为所有线程都是轮流占用CPU。多个线程慢于一个线程,因为其他线程还要先调度出来,再等待。
在多核CPU机器上,多线程代码运行性能会非常糟糕,比单核更糟糕。因为这时候多一个步骤,不同的CPU再竞争GIL,GIL只有一个。Python在多核CPU上的多核CPU也只有单线程在跑程序。

可以有哪些解决办法呢?【绕开GIL的影响】

使用多进程(多进程之间没有GIL限制)
使用Jython, IronPython等无GIL的解释器
使用协程(高效的单线程模式)
GIL的设置有其优点和可取之处,在Cpython解释器框架之下难以绕过这一限制。可以用PyPy解释器,麻烦之处在于很多第三方库在PyPy下无法使用,或者重新安装第三方库的PyPy版本。运行时候,PyPy **.py即可。Cpython下是Python **.py。
I/O的多线程还是快于单线程,因为优先级在获取GIL之上,I/O并行运算的时候,GIL处于release状态。
 

 注意:但是多进程的时候要注意点,就是如果把开启进程的对象放到全局位置的话,会造成在开启子进程的时候,子进程又会调用这个全局对象,造成再一次开启子进程,这就导致子进程里再开启子进程,从而就会报错。因为子进程再开启子进程是不允许的,这个会造成无限死循环。

猜你喜欢

转载自blog.csdn.net/yangdashi888/article/details/103736036