面试头条的时候:Python的多线程有什么特点?当时直接答不会。。
结论:Python的多线程是假的,不能有效的利用多核。
先看几个例子,
1. python的多线程
#coding=utf-8 from multiprocessing import Pool from threading import Thread from multiprocessing import Process def loop(): while True: pass if __name__ == '__main__': for i in range(3): t = Thread(target=loop) t.start() while True: pass
我的电脑是4核,所以我开了4个线程,看一下CPU资源占有率:
我们发现CPU利用率并没有占满,大致相当于单核水平。而如果我们变成进程呢?
2. python的多进程#coding=utf-8 from multiprocessing import Pool from threading import Thread from multiprocessing import Process def loop(): while True: pass if __name__ == '__main__': for i in range(3): t = Process(target=loop) t.start() while True: pass
结果直接飙到了100%,说明进程是可以利用多核的!
我们再用Java/C重写一下,开启多线程。
3. java的多线程
package com.darrenchan.thread; public class TestThread { public static void main(String[] args) { for (int i = 0; i < 3; i++) { new Thread(new Runnable() { @Override public void run() { while (true) { } } }).start(); } while(true){ } } }
由此可见,Java中的多线程是可以利用多核的,这是真正的多线程!而Python中的多线程只能利用单核,这是假的多线程!
为什么会这样?
GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。
GIL是Python解释器设计的历史遗留问题,通常我们用的解释器是官方实现的CPython,要真正利用多核,除非重写一个不带GIL的解释器。
怎么解决呢?
如果一定要通过多线程利用多核,那只能通过C扩展来实现,例如Numpy底层就是C++实现的。不过这样就失去了Python简单易用的特点
另一方面,Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。
参考链接:
1. https://www.liaoxuefeng.com/wiki/1016959663602400/1017629247922688