面試頭條的時候: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
2. 為什麼有人說 Python 的多線程是雞肋呢? - DarrenChan陳馳的回答 - 知乎
個性簽名:時間會解決一切