進(jìn)程
進(jìn)程是具有一定獨(dú)立功能的程序關(guān)于某個數(shù)據(jù)集合上的一次運(yùn)行活動货徙,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個獨(dú)立單位左权。每個進(jìn)程都有自己的獨(dú)立內(nèi)存空間,不同進(jìn)程通過進(jìn)程間通信來通信痴颊。由于進(jìn)程比較重赏迟,占據(jù)獨(dú)立的內(nèi)存,所以上下文進(jìn)程間的切換開銷(棧蠢棱、寄存器锌杀、虛擬內(nèi)存、文件句柄等)比較大泻仙,但相對比較穩(wěn)定安全糕再。
進(jìn)程是系統(tǒng)里的程序,擁有獨(dú)立的系統(tǒng)資源玉转,系統(tǒng)資源分配調(diào)度的獨(dú)立單位突想,切換開銷大,但比較穩(wěn)定安全究抓。
線程
線程是指進(jìn)程內(nèi)的一個執(zhí)行單元猾担,也是進(jìn)程內(nèi)的可調(diào)度實(shí)體。線程是進(jìn)程的一個實(shí)體刺下,是CPU調(diào)度和分派的基本單位绑嘹,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位。線程自己基本上不擁有系統(tǒng)資源橘茉,只擁有一點(diǎn)在運(yùn)行中必不可少的資源(如程序計(jì)算器工腋,一組寄存器和棧)姨丈,但是它可與同屬一個進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源。線程間通信主要通過共享內(nèi)存擅腰,上下文切換很快蟋恬,資源開銷較少,但相比進(jìn)程不夠穩(wěn)定容易丟失數(shù)據(jù)趁冈。
線程是進(jìn)程的執(zhí)行單元筋现,進(jìn)程內(nèi)的可調(diào)度實(shí)體,是CPU調(diào)度和分派的基本單位箱歧,基本不擁有系統(tǒng)資源矾飞,與同進(jìn)程中的其他線程共享進(jìn)程資源,通過共享內(nèi)存進(jìn)行通信呀邢,切換快洒沦,資源開銷少,但不穩(wěn)定容易丟失數(shù)據(jù)价淌。
協(xié)程
GIL:全局解釋器鎖(Global Interpreter Lock)是計(jì)算機(jī)程序設(shè)計(jì)語言解釋器用于同步線程的一種機(jī)制申眼,它使得任何時刻僅有一個線程在執(zhí)行。即便在多核心處理器上蝉衣,使用GIL的解釋器也只允許同一時間執(zhí)行一個線程括尸。 由于GIL的存在,導(dǎo)致python多線程性能甚至比單線程更糟病毡。
協(xié)程:又稱為線程濒翻,纖程,Coroutine啦膜。協(xié)程的作用有送,是在執(zhí)行函數(shù)A時,可以隨時中斷僧家,去執(zhí)行函數(shù)B雀摘,然后中斷繼續(xù)執(zhí)行函數(shù)A(可以自由切換)。但這一過程并不是函數(shù)調(diào)用(沒有調(diào)用語句)八拱,這一整個過程看似像多線程阵赠,然而協(xié)程只有一個線程執(zhí)行。
python對協(xié)程的支持是通過生成器(Generator肌稻,存在yield的地方被執(zhí)行到時暫停清蚀,等待再次被觸發(fā))實(shí)現(xiàn)的。
協(xié)程是一種用戶態(tài)的輕量級線程灯萍,協(xié)程的調(diào)度完全由用戶控制轧铁。從技術(shù)的角度來說每聪,“協(xié)程就是你可以暫停執(zhí)行的函數(shù)”旦棉。協(xié)程擁有自己的寄存器上下文和棧齿风。協(xié)程調(diào)度切換時,將寄存器上下文和棧保存到其他地方绑洛,在切回來的時候救斑,恢復(fù)先前保存的寄存器上下文和棧,直接操作棧則基本沒有內(nèi)核切換的開銷真屯,可以不加鎖的訪問全局變量脸候,所以上下文的切換非常快绑蔫。
協(xié)程是用戶態(tài)輕量級線程运沦,調(diào)度完全由用戶控制,技術(shù)角度可暫停執(zhí)行的函數(shù)配深,擁有自己的上下文和棧携添,切換沒有內(nèi)核切換的開銷,可以不加鎖的訪問全局變量篓叶,所以上下文切換非沉衣樱快。
代碼示例
import asyncio
future = asyncio.Future()
async def coro1():
print("wait 1 second")
await asyncio.sleep(1)
print("set_result")
future.set_result('data')
async def coro2():
result = await future
print(result)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait([
coro1()
coro2()
]))
loop.close()
輸出結(jié)果:
wait 1 second
(大約等待1秒)
set_result
data
線程和進(jìn)程的區(qū)別:
- 地址空間:線程是進(jìn)程內(nèi)的一個執(zhí)行單元缸托,進(jìn)程內(nèi)至少有一個線程左敌,他們共享進(jìn)程的地址空間,而進(jìn)程有自己獨(dú)立的地址空間
- 資源擁有:進(jìn)程是資源分配和擁有的單位俐镐,同一個進(jìn)程內(nèi)的線程共享進(jìn)程的資源
- 線程是處理器調(diào)度的基本單位矫限,但進(jìn)程不是
- 二者均可并發(fā)執(zhí)行
- 每個獨(dú)立的線程有一個程序運(yùn)行的入口、順序執(zhí)行序列和程序的出口佩抹,但是線程不能夠獨(dú)立執(zhí)行奇唤,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個線程執(zhí)行控制
協(xié)程與線程的區(qū)別:
- 一個線程可以多個協(xié)程匹摇,一個進(jìn)程也可以單獨(dú)擁有多個協(xié)程
- 線程進(jìn)程都是同步機(jī)制咬扇,而協(xié)程則是異步
- 協(xié)程能保留上一次調(diào)用時的狀態(tài),每次過程重入時廊勃,就相當(dāng)于進(jìn)入上一次調(diào)用的狀態(tài)
- 線程是搶占式懈贺,而協(xié)程是非搶占式的,所以需要用戶自己釋放使用權(quán)來切換到其他協(xié)程坡垫,因此同一時間其實(shí)只有一個協(xié)程擁有運(yùn)行權(quán)梭灿,相當(dāng)于單線程的能力
- 協(xié)程并不是取代線程,而是抽象于線程之上冰悠,線程是被分割的CPU資源堡妒,協(xié)程是組織好的代碼流程,協(xié)程需要線程來承載運(yùn)行溉卓,線程是協(xié)程的資源皮迟,但協(xié)程不會直接使用線程搬泥,協(xié)程直接利用的是執(zhí)行器(interceptor),執(zhí)行器可以管理任意線程或線程池伏尼,可以是當(dāng)前線程忿檩,UI線程,或新建線程爆阶。
- 線程是協(xié)程的資源燥透。協(xié)程通過Interceptor來間接使用線程這個資源