進程和線程(4)-進程 vs. 線程

進程 vs. 線程

咱們介紹了多進程和多線程,這是實現多任務最經常使用的兩種方式。如今,咱們來討論一下這兩種方式的優缺點。編程

首先,要實現多任務,一般咱們會設計Master-Worker模式,Master負責分配任務,Worker負責執行任務,所以,多任務環境下,一般是一個Master,多個Worker。服務器

若是用多進程實現Master-Worker,主進程就是Master,其餘進程就是Worker。網絡

若是用多線程實現Master-Worker,主線程就是Master,其餘線程就是Worker。多線程

多進程模式最大的優勢就是穩定性高,由於一個子進程崩潰了,不會影響主進程和其餘子進程。(固然主進程掛了全部進程就全掛了,可是Master進程只負責分配任務,掛掉的機率低)著名的Apache最先就是採用多進程模式。併發

多進程模式的缺點是建立進程的代價大,在Unix/Linux系統下,用fork調用還行,在Windows下建立進程開銷巨大。另外,操做系統能同時運行的進程數也是有限的,在內存和CPU的限制下,若是有幾千個進程同時運行,操做系統連調度都會成問題。異步

多線程模式一般比多進程快一點,可是也快不到哪去,並且,多線程模式致命的缺點就是任何一個線程掛掉均可能直接形成整個進程崩潰,由於全部線程共享進程的內存。在Windows上,若是一個線程執行的代碼出了問題,你常常能夠看到這樣的提示:「該程序執行了非法操做,即將關閉」,其實每每是某個線程出了問題,可是操做系統會強制結束整個進程。異步編程

在Windows下,多線程的效率比多進程要高,因此微軟的IIS服務器默認採用多線程模式。因爲多線程存在穩定性的問題,IIS的穩定性就不如Apache。爲了緩解這個問題,IIS和Apache如今又有多進程+多線程的混合模式,真是把問題越搞越複雜。操作系統

線程切換

不管是多進程仍是多線程,只要數量一多,效率確定上不去,爲何呢?線程

咱們打個比方,假設你不幸正在準備中考,天天晚上須要作語文、數學、英語、物理、化學這5科的做業,每項做業耗時1小時。設計

若是你先花1小時作語文做業,作完了,再花1小時作數學做業,這樣,依次所有作完,一共花5小時,這種方式稱爲單任務模型,或者批處理任務模型。

假設你打算切換到多任務模型,能夠先作1分鐘語文,再切換到數學做業,作1分鐘,再切換到英語,以此類推,只要切換速度足夠快,這種方式就和單核CPU執行多任務是同樣的了,以幼兒園小朋友的眼光來看,你就正在同時寫5科做業。

可是,切換做業是有代價的,好比從語文切到數學,要先收拾桌子上的語文書本、鋼筆(這叫保存現場),而後,打開數學課本、找出圓規直尺(這叫準備新環境),才能開始作數學做業。操做系統在切換進程或者線程時也是同樣的,它須要先保存當前執行的現場環境(CPU寄存器狀態、內存頁等),而後,把新任務的執行環境準備好(恢復上次的寄存器狀態,切換內存頁等),才能開始執行。這個切換過程雖然很快,可是也須要耗費時間。若是有幾千個任務同時進行,操做系統可能就主要忙着切換任務,根本沒有多少時間去執行任務了,這種狀況最多見的就是硬盤狂響,點窗口無反應,系統處於假死狀態。

因此,多任務一旦多到一個限度,就會消耗掉系統全部的資源,結果效率急劇降低,全部任務都作很差。

計算密集型 vs. IO密集型

是否採用多任務的第二個考慮是任務的類型。咱們能夠把任務分爲計算密集型和IO密集型。

計算密集型任務的特色是要進行大量的計算,消耗CPU資源,好比計算圓周率、對視頻進行高清解碼等等,全靠CPU的運算能力。這種計算密集型任務雖然也能夠用多任務完成,可是任務越多,花在任務切換的時間就越多,CPU執行任務的效率就越低,因此,要最高效地利用CPU,計算密集型任務同時進行的數量應當等於CPU的核心數。

計算密集型任務因爲主要消耗CPU資源,所以,代碼運行效率相當重要。Python這樣的腳本語言運行效率很低,徹底不適合計算密集型任務。對於計算密集型任務,最好用C語言編寫。

第二種任務的類型是IO密集型,涉及到網絡、磁盤IO的任務都是IO密集型任務,這類任務的特色是CPU消耗不多,任務的大部分時間都在等待IO操做完成(由於IO的速度遠遠低於CPU和內存的速度)。對於IO密集型任務,任務越多,CPU效率越高,但也有一個限度。常見的大部分任務都是IO密集型任務,好比Web應用。

IO密集型任務執行期間,99%的時間都花在IO上,花在CPU上的時間不多,所以,用運行速度極快的C語言替換用Python這樣運行速度極低的腳本語言,徹底沒法提高運行效率。對於IO密集型任務,最合適的語言就是開發效率最高(代碼量最少)的語言,腳本語言是首選,C語言最差。

異步IO

考慮到CPU和IO之間巨大的速度差別,一個任務在執行的過程當中大部分時間都在等待IO操做,單進程單線程模型會致使別的任務沒法並行執行,所以,咱們才須要多進程模型或者多線程模型來支持多任務併發執行。

現代操做系統對IO操做已經作了巨大的改進,最大的特色就是支持異步IO。若是充分利用操做系統提供的異步IO支持,就能夠用單進程單線程模型來執行多任務,這種全新的模型稱爲事件驅動模型,Nginx就是支持異步IO的Web服務器,它在單核CPU上採用單進程模型就能夠高效地支持多任務。在多核CPU上,能夠運行多個進程(數量與CPU核心數相同),充分利用多核CPU。因爲系統總的進程數量十分有限,所以操做系統調度很是高效。用異步IO編程模型來實現多任務是一個主要的趨勢。

對應到Python語言,單進程的異步編程模型稱爲協程,有了協程的支持,就能夠基於事件驅動編寫高效的多任務程序。咱們會在後面討論如何編寫協程。

相關文章
相關標籤/搜索