在群里經常聽到這樣的爭執,有人是虛心請教問題,有人就大放厥詞因為這個說python辣雞。而爭論的核心無非就是,python的多線程在同一時刻只會有一條線程跑在CPU里面,其他線程都在睡覺。這是真的嗎?
是真的。這個就是因為傳說中的GIL(全局解釋鎖)的存在。不明白這個詞的可以去百度一下,我解釋不好(大家都是程序猿你懂的,我寫錯一個詞就要挨噴了,就算我沒寫錯對方理解錯了,我也一樣要挨噴)。有了這樣一個看似bug的存在,就導致了上面說的情況:同一時刻內,python的線程只有一條在CPU里面運行。
所以python的多線程就沒用咯?當然不是。這要看程序是什么樣的。如果是一個計算為主的程序(專業一點稱為CPU密集型程序),這一點確實是比較吃虧的,每個線程運行一遍,就相當於單線程再跑,甚至比單線程還要慢——CPU切換線程的上下文也是要有開銷的。但是,如果是一個磁盤或網絡為主的程序(IO密集型)就不同了。一個線程處在IO等待的時候,另一個線程還可以在CPU里面跑,有時候CPU閑着沒事干,所有的線程都在等着IO,這時候他們就是同時的了,而單線程的話此時還是在一個一個等待的。我們都知道IO的速度比起CPU來是慢到令人發指的,python的多線程就在這時候發揮作用了。比方說多線程網絡傳輸,多線程往不同的目錄寫文件,等等。
話說回來,CPU密集型的程序用python來做,本身就不合適。跟C,Go,Java的速度比,實在性能差到沒法說。你當然可以寫個C擴展來實現真正的多線程,用python來調用,那樣速度是快。我們之所以用python來做,只是因為開發效率超高,可以快速實現。
最后補充幾點:
- python中要想利用好CPU,還是用多進程來做吧。或者,可以使用協程。multiprocessing和gevent在召喚你。
- GIL不是bug,Guido也不是水平有限才留下這么個東西。龜叔曾經說過,嘗試不用GIL而用其他的方式來做線程安全,結果python語言整體效率又下降了一倍,權衡利弊,GIL是最好的選擇——不是去不掉,而是故意留着的。
- 想讓python計算速度快起來,又不想寫C?用pypy吧,這才是真正的大殺器。