Python的伪多线程

众所周知,python 这门语言在单个脚本运行的时候只能利用单个核心,但是 python 本身又有 threading 这个库来实现所谓的多线程。那么 Python 的多线程到底是个什么玩意呢=_=

简单写一个验证程序

import threading

def loop():
    i=0
    while 1:
        i=i+1

threading.Thread(target=loop).start()
threading.Thread(target=loop).start()

我们期望的结果是在一个多核心 cpu 的系统上,有两个核心被占满。那么实际跑一下看看结果

实际的效果

可以发现确实跑在了两个核心上,但是 wait…怎么一个核心只有 50%的占用率,这 python 的多线程未免有些抽象了。经过查阅资料$^1$之后,发现了 Python 中存在的一个祖传史山 GIL,翻译过来就是全局变量锁。

抽象就抽象在,同一时刻只能有一个线程获取我们的 GIL 锁,当这个线程拿到锁之后,才可以读取并执行只属于 ta 的字节码,时间片一过或遇到 IO 等待$^2$,这个锁就又要交还给其它的线程使用,这就导致同一时刻只有一个线程可以处于活动状态。其实这和协程也就没什么区别了。

总结一下,高并发,低 IO 调用的程序不要用 python 写,如果一定要用的话,那么就开多进程,使用进程间的通信来实现。虽然 python 中的线程确实是标准的 posix 实现,但是由于拉跨的 GIL,实际的效果还不如开协程来实现逻辑。

参考资料:

2023/7/10 附:似乎 GIL 将可以在之后的新版的 Python 中关闭。可喜可贺