本文研究的主要是python中協(xié)程的相關(guān)問題,具體介紹如下。
Num01–>協(xié)程的定義
協(xié)程,又稱微線程,纖程。英文名Coroutine。
首先我們得知道協(xié)程是啥?協(xié)程其實(shí)可以認(rèn)為是比線程更小的執(zhí)行單元。 為啥說他是一個(gè)執(zhí)行單元,因?yàn)樗詭PU上下文。這樣只要在合適的時(shí)機(jī), 我們可以把一個(gè)協(xié)程 切換到另一個(gè)協(xié)程。 只要這個(gè)過程中保存或恢復(fù) CPU上下文那么程序還是可以運(yùn)行的。
那么這個(gè)過程看起來和線程差不多。其實(shí)不然, 線程切換從系統(tǒng)層面遠(yuǎn)不止保存和恢復(fù) CPU上下文這么簡(jiǎn)單。 操作系統(tǒng)為了程序運(yùn)行的高效性每個(gè)線程都有自己緩存Cache等等數(shù)據(jù),操作系統(tǒng)還會(huì)幫你做這些數(shù)據(jù)的恢復(fù)操作。 所以線程的切換非常耗性能。但是協(xié)程的切換只是單純的操作CPU的上下文,所以一秒鐘切換個(gè)上百萬次系統(tǒng)都抗的住。
協(xié)程有一個(gè)問題,就是系統(tǒng)并不感知,所以操作系統(tǒng)不會(huì)幫你做切換。 那么誰來幫你做切換?讓需要執(zhí)行的協(xié)程更多的獲得CPU時(shí)間才是問題的關(guān)鍵。
舉個(gè)例子如下:
目前的協(xié)程框架一般都是設(shè)計(jì)成 1:N 模式。所謂 1:N 就是一個(gè)線程作為一個(gè)容器里面放置多個(gè)協(xié)程。 那么誰來適時(shí)的切換這些協(xié)程?答案是有協(xié)程自己主動(dòng)讓出CPU,也就是每個(gè)協(xié)程池里面有一個(gè)調(diào)度器, 這個(gè)調(diào)度器是被動(dòng)調(diào)度的。意思就是他不會(huì)主動(dòng)調(diào)度。而且當(dāng)一個(gè)協(xié)程發(fā)現(xiàn)自己執(zhí)行不下去了(比如異步等待網(wǎng)絡(luò)的數(shù)據(jù)回來,但是當(dāng)前還沒有數(shù)據(jù)到), 這個(gè)時(shí)候就可以由這個(gè)協(xié)程通知調(diào)度器,這個(gè)時(shí)候執(zhí)行到調(diào)度器的代碼,調(diào)度器根據(jù)事先設(shè)計(jì)好的調(diào)度算法找到當(dāng)前最需要CPU的協(xié)程。 切換這個(gè)協(xié)程的CPU上下文把CPU的運(yùn)行權(quán)交個(gè)這個(gè)協(xié)程,直到這個(gè)協(xié)程出現(xiàn)執(zhí)行不下去需要等等的情況,或者它調(diào)用主動(dòng)讓出CPU的API之類,觸發(fā)下一次調(diào)度。
在IO密集型的程序中由于IO操作遠(yuǎn)遠(yuǎn)慢于CPU的操作,所以往往需要CPU去等IO操作。 同步IO下系統(tǒng)需要切換線程,讓操作系統(tǒng)可以在IO過程中執(zhí)行其他的東西。 這樣雖然代碼是符合人類的思維習(xí)慣但是由于大量的線程切換帶來了大量的性能的浪費(fèi),尤其是IO密集型的程序。
所以人們發(fā)明了異步IO。就是當(dāng)數(shù)據(jù)到達(dá)的時(shí)候觸發(fā)我的回調(diào)。來減少線程切換帶來性能損失。 但是這樣的壞處也是很大的,主要的壞處就是操作被 “分片” 了,代碼寫的不是 “一氣呵成” 這種。 而是每次來段數(shù)據(jù)就要判斷 數(shù)據(jù)夠不夠處理哇,夠處理就處理吧,不夠處理就在等等吧。這樣代碼的可讀性很低,其實(shí)也不符合人類的習(xí)慣。
新聞熱點(diǎn)
疑難解答
圖片精選