Python 线程和进程和协程总结
Python 線程和進(jìn)程和協(xié)程總結(jié)
線程和進(jìn)程和協(xié)程
進(jìn)程
進(jìn)程是程序執(zhí)行時的一個實例,是擔(dān)當(dāng)分配系統(tǒng)資源(CPU時間、內(nèi)存等)的基本單位;
進(jìn)程有獨立的地址空間,一個進(jìn)程崩潰后,在保護(hù)模式下不會對其它進(jìn)程產(chǎn)生影響;
進(jìn)程間可以通過信號、信號量、共享內(nèi)存、管道、隊列等來進(jìn)行通信;
進(jìn)程創(chuàng)建、銷毀、上下文切換帶來的開銷成本都很大;
線程
線程是進(jìn)程的一個實體,作為獨立運行和獨立調(diào)度的基本單位。
線程可與同屬一個進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源。
線程只是一個進(jìn)程中的不同執(zhí)行路徑,沒有單獨的地址空間,一個線程死掉就會導(dǎo)致整個進(jìn)程死掉。
線程創(chuàng)建、銷毀、上下文切換帶來的開銷要比進(jìn)程小得多;
協(xié)程
協(xié)程的控制有應(yīng)用程序控制,非搶占式的;
切換快,開銷相較線程更小,所以可以開更多的協(xié)程;
具體使用參考Python 協(xié)程總結(jié)
多線程和多進(jìn)程
多線程
優(yōu)點
它是一種非常"節(jié)儉"的多任務(wù)操作方式。我們知道,在Linux系統(tǒng)下,啟動一個新的進(jìn)程必須分配給它獨立的地址空間,建立眾多的數(shù)據(jù)表來維護(hù)它的代碼段、堆棧段和數(shù)據(jù)段,這是一種"昂貴"的多任務(wù)工作方式。而運行于一個進(jìn)程中的多個線程,它們彼此之間使用相同的地址空間,共享大部分?jǐn)?shù)據(jù),啟動一個線程所花費的空間遠(yuǎn)遠(yuǎn)小于啟動一個進(jìn)程所花費的空間,而且,線程間彼此切換所需的時間也遠(yuǎn)遠(yuǎn)小于進(jìn)程間切換所需要的時間。
線程間方便的通信機制,對不同進(jìn)程來說,它們具有獨立的數(shù)據(jù)空間,要進(jìn)行數(shù)據(jù)的傳遞只能通過通信的方式進(jìn)行,這種方式不僅費時,而且很不方便。線程則不然,由于同一進(jìn)程下的線程之間共享數(shù)據(jù)空間,所以一個線程的數(shù)據(jù)可以直接為其它線程所用。
提高應(yīng)用程序響應(yīng)。這對圖形界面的程序尤其有意義,當(dāng)一個操作耗時很長時,整個系統(tǒng)都會等待這個操作,此時程序不會響應(yīng)鍵盤、鼠標(biāo)、菜單的操作,而使用多線程技術(shù),將耗時長的操作(time consuming)置于一個新的線程,可以避免這種尷尬的情況。
使多CPU系統(tǒng)更加有效。操作系統(tǒng)會保證當(dāng)前線程數(shù)不大于CPU數(shù)目時,不同的線程運行于不同的CPU上。
GIL
全局解釋器鎖是在實現(xiàn)Python解析器(CPython)時所引入的一個概念。每個線程在執(zhí)行的過程都需要先獲取GIL,保證同一時刻只有一個線程可以執(zhí)行代碼。
Q&A: 為什么說GIL對于CPU密集型任務(wù)不友好,而對于IO密集型任務(wù)比較友好呢?
這是因為GIL的釋放邏輯是當(dāng)前線程遇見IO操作或者ticks計數(shù)達(dá)到100(ticks可以看作是python自身的一個計數(shù)器,專門做用于GIL,每次釋放后歸零,這個計數(shù)可以通過 sys.setcheckinterval 來調(diào)整),進(jìn)行釋放。而每次釋放GIL鎖,線程進(jìn)行鎖競爭、切換線程,會消耗資源。
那CPU密集型任務(wù)(各種循環(huán)處理、計數(shù)等等),在這種情況下,ticks計數(shù)很快就會達(dá)到閾值,然后觸發(fā)GIL的釋放與再競爭(多個線程來回切換當(dāng)然是需要消耗資源的),但是對于IO密集型任務(wù),多線程能夠有效提升效率(單線程下有IO操作會進(jìn)行IO等待,造成不必要的時間浪費,而開啟多線程能在線程A等待時,自動切換到線程B,可以不浪費CPU的資源,從而能提升程序執(zhí)行效率)。因此說GIL對于CPU密集型任務(wù)不友好,而對于IO密集型任務(wù)比較友好。
解決方案
multiprocessing庫的出現(xiàn)很大程度上是為了彌補thread庫因為GIL而低效的缺陷,它完整的復(fù)制了一套thread所提供的接口方便遷移。唯一的不同就是它使用了多進(jìn)程而不是多線程。每個進(jìn)程有自己的獨立的GIL,因此也不會出現(xiàn)進(jìn)程之間的GIL爭搶。當(dāng)然multiprocessing也不是萬能良藥。它的引入會增加程序?qū)崿F(xiàn)時線程間數(shù)據(jù)通訊和同步的困難。Python的多線程在多核CPU上,只對于IO密集型計算產(chǎn)生正面效果;而當(dāng)至少有一個CPU密集型線程存在時,那么多線程效率會由于GIL而大幅下降,這個時候就得使用多進(jìn)程;
多進(jìn)程
Python中的多線程因為GIL的關(guān)系并不算是真正的多線程,如果想要充分地使用多核CPU的資源,大部分情況需要使用多進(jìn)程。multiprocessing支持子進(jìn)程、通信和共享數(shù)據(jù)、執(zhí)行不同形式的同步,提供了Process、Queue、Pipe、Lock等組件。
談?wù)刾ython的GIL、多線程、多進(jìn)程
轉(zhuǎn)載于:https://www.cnblogs.com/George1994/p/10615435.html
總結(jié)
以上是生活随笔為你收集整理的Python 线程和进程和协程总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaWeb——c:forEach v
- 下一篇: json-server-----》基本使