Python多线程测试和探究
我们直接通过下面的死循环来测试:
import threading
def loop():
x = 0
while True:
x = x ^ 1
t1 = threading.Thread(target=loop)
t2 = threading.Thread(target=loop)
t1.start()
t2.start()
多核CPU应该同时执行多个线程, 也就是我们执行1个死循环, 应该会跑满1个CPU至100%, 执行2个死循环, 会占用200%的cpu.
但是我们用Python执行会发现, 1个和2个线程都执行占用到100%CPU, 而无法达到200%CPU.
我们从<<Python参考手册>>中可以看到:
在大多数系统上,Python同时支持消息传递和基于线程的并发编程。尽管大多数程序员熟悉的往往是线程接口,但实际上Python线程受到的限制有很多。尽管最低限度是线程安全的,但Python解释器还是使用了内部的GIL(GlobalInterpreterLock,全局解释器锁定定),在任意指定的时刻只允许单个 Python线程执行。无论系统上存在多少个可用的CPU核心,这限制了Python程序只能在一个处理器上运行。尽管GIL经常是Python社区中争论的热点,但在可以预见的将来它都不可能消失.
也就是Python因为 全局解释器锁- GIL的原因, 并没有实现真正的多线程.
Python代码的执行是由python解释器来控制的, 尽管Python解释器允许多线程的存在, 但是由于GIL一次只允许一个线程执行, 所以只能利用一个CPU, 同时只能有一个线程在执行.
GIL 每执行100条字节码, 解释器就自动释放GIL锁, 让别的线程有机会执行.
这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以, 多线程在Python中只能交替执行, 即使100个线程跑在100核cpu上, 也只能用到1核.
python解释器和GIL怎么配合工作:
1.设置GIL
2.切换到一个线程去执行。
3.运行。
4.把线程设置为睡眠状态。
5.解锁GIL。
6.再次重复以上步骤。
我们使用Java或者C++就可以实现200%CPU的利用.
虽然没有真正的多线程, 但是我们Python中的协程, 对于IO操作也是非常快的.