Python進(jìn)程、線程、協(xié)程的對(duì)比

1. 執(zhí)行過(guò)程

  • 每個(gè)線程有一個(gè)程序運(yùn)行的入口、順序執(zhí)行序列和程序的出口。但是線程不能夠獨(dú)立執(zhí)行,必須依存在進(jìn)程中,由進(jìn)程提供多個(gè)線程執(zhí)行控制。每個(gè)線程都有他自己的一組CPU寄存器,稱為線程的上下文,該上下文反映了線程上次運(yùn)行該線程的CPU寄存器的狀態(tài)。
  • 協(xié)程,又稱微線程,Coroutine。執(zhí)行過(guò)程中,在子程序內(nèi)部可中斷,然后轉(zhuǎn)而執(zhí)行別的子程序,在適當(dāng)?shù)臅r(shí)候再返回來(lái)接著執(zhí)行。實(shí)際上就是對(duì)函數(shù)調(diào)用流程的一種控制方式,讓函數(shù)互相協(xié)作配合,這就是協(xié)程。

2. 調(diào)度方式

  • 進(jìn)程和線程完全由操作系統(tǒng)負(fù)責(zé)調(diào)度,程序自己不能決定什么時(shí)候執(zhí)行,執(zhí)行多長(zhǎng)時(shí)間。
  • 協(xié)程則是在程序中,自己負(fù)責(zé)調(diào)度,更加靈活,但復(fù)雜度較高。

3. 運(yùn)行效率

  • 進(jìn)程是重量級(jí)別的程序,創(chuàng)建和銷毀開(kāi)銷大。
  • 線程是輕量級(jí)別的程序,相比進(jìn)程下創(chuàng)建和銷毀開(kāi)銷小,切換速度較快。
  • 協(xié)程則是單線程的異步編程模型。和多線程比,線程數(shù)量越多,CPU就會(huì)花掉更多時(shí)間在切換中,而沒(méi)有線程切換、保存上下文的開(kāi)銷的協(xié)程,相比下運(yùn)行效率則更高。第二大優(yōu)勢(shì)就是不需要多線程的鎖機(jī)制,因?yàn)橹挥幸粋€(gè)線程,也不存在同時(shí)寫變量沖突,在協(xié)程中控制共享資源不加鎖,所以協(xié)程性能優(yōu)勢(shì)更加明顯。

4. CPU利用

  • 線程和協(xié)程由于CPython中全局解釋器鎖GIL的問(wèn)題,只能使用到單核CPU的計(jì)算資源
  • 進(jìn)程則可以運(yùn)行多個(gè)(數(shù)量與CPU核心數(shù)相同),充分利用多核CPU

CPython解釋器本身不是線程安全的,因此需要全局解釋器鎖GIL,一次只允許一個(gè)線程執(zhí)行Python字節(jié)碼。因此一個(gè)Python進(jìn)程不能同時(shí)使用到多個(gè)CPU核心。
然而,標(biāo)準(zhǔn)庫(kù)中所有執(zhí)行阻塞型 IO 操作的函數(shù),在等待結(jié)果返回時(shí)都會(huì)釋放GIL。這意味著盡管有GIL,Python線程還是能在 IO 密集型任務(wù)中一展身手。 引用自《流暢的Python》

5. 最佳實(shí)踐

  • 線程和協(xié)程推薦在IO密集型的任務(wù)(比如網(wǎng)絡(luò)調(diào)用)中使用,而在CPU密集型的任務(wù)中,表現(xiàn)較差。
  • 對(duì)于CPU密集型的任務(wù),則需要多個(gè)進(jìn)程,繞開(kāi)GIL的限制,利用所有可用的CPU核心,提高效率。
  • 所以大并發(fā)下的最佳實(shí)踐就是多進(jìn)程+協(xié)程,既充分利用多核,又充分發(fā)揮協(xié)程的高效率,可獲得極高的性能。
    順便一提,非常流行的一個(gè)爬蟲(chóng)框架Scrapy就是用到異步框架Twisted來(lái)進(jìn)行任務(wù)的調(diào)度,這也是Scrapy框架高性能的原因之一。
參考鏈接

廖雪峰的Python教程
廖雪峰 協(xié)程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容