協程到底是什么?看完這個故事明明白白!


神秘使者

“久聞Java語言跨越平台,框架眾多,不過二十年功夫,就已晉升天下第一編程語言,今日一見,果然名不虛傳吶!”

“使者先生您過獎了,咱們快些走,國王陛下已經等候多時了”

今日,Java帝國朝堂之上迎來了一位神秘的來賓。

 

 

來到大殿之上,只見國王正襟危坐,閉目養神,不怒自威,堂下群臣咸集,紛紛側目。

“來者何人?”,國王一旁的內侍問到。

“我乃GoLang帝國使者——Goroutine”,使者答道。

 

 

“GoLang帝國?何方番邦小國?寡人竟從未聽聞”,國王閉眼說到。

說罷,群臣皆笑了起來。

“來此所為何事?”,內侍繼續問到。

使者回答:“我此行特為傳道而來”

說完,國王睜開了眼睛,“傳道?我Java帝國乃天下第一編程帝國,只有我們傳出去,哪有學別人之道?”

使者不卑不亢,說到:“Java帝國雖如日中天,但卻有一處缺陷,假以時日,必成大患”

“哦,你倒是說說看,如若言語不通,即刻轟出殿去。”,國王厲聲喝到。

“敢問陛下,Java線程執行到阻塞函數時,該當如何?”,使者問到。

一旁的線程大臣見狀,上前說到:“遇到阻塞那自然要被操作系統掛起,切換到別的線程”

“敢問大人,線程切換是否需要成本?如果大量線程頻繁切換,成本又當如何?”,使者追問到。

“你若關心這個問題,那就不用阻塞函數,通過異步回調來進行”,線程大臣答道。

使者嘴角上揚,微微一笑,“好一個異步回調!異步回調確實不用阻塞,不過它有兩宗罪,其一:割裂了原來的代碼業務邏輯,其二:陷入回調地獄難以維護”

 

 

“這也不行,那也不行,你這人還真難伺候”,線程大臣有些急了。

使者轉身面向國王說到:“啟稟陛下,我有一法,可讓線程遇到阻塞函數后不需切換線程,也不用異步回調還可以繼續運行下去,是高並發開發神技”

國王一聽來了興趣:“哦,還有這種事?說來聽聽”

使者拜了一拜,說到:“線程可以在遇到阻塞的地方后,保存執行的上下文,轉而去執行別處的代碼。待阻塞的請求完成后,再轉而回去繼續執行”

 

 

國王不解,問到:“什么叫轉而去執行別處的代碼?什么叫回去繼續執行?這函數執行到一半還能中途退出再回來?”

“是的,沒錯!”,使者回答。

此話一出,朝堂上議論紛紛,群臣都露出了鄙夷的笑容。

“簡直荒謬!函數執行從進入到return退出,從來都是一氣呵成,哪有中途執行一半退出,再回來接着執行的道理?簡直聞所未聞!”,一旁的線程大臣說到。

使者繼續說到:“一氣呵成?恐怕不是吧?線程執行函數中途,遇到時間片用完或者遇到I/O阻塞,就會被操作系統保存上下文后掛起,切換到其他線程。而后等到機會再回過頭繼續執行,不是嗎?”

 

 

線程大臣怒斥道:“強詞奪理!你說的這情況是操作系統在調度管理多個線程,對咱們的應用層線程來說都是透明的,無需關心”

使者沒有退讓,卻問道:“既然操作系統可以調度管理多個線程,那為何線程不可以調度管理函數的執行?

群臣再次交頭接耳,議論起來。

“陛下,此番邦使者妖言惑眾,微臣建議即刻逐出大殿,以正視聽!”

國王應允,隨即遣人上前。

不待侍衛上前,使者自行離去,邊走邊說到:“可嘆!堂堂Java帝國,卻容不下一個新技術”

臨別相會

使者心灰意冷,打算離開Java帝國,卻在半道上被人給攔了下來。

“先生請留步,我家主人請先生府上相會”

使者來到府上,原來主人乃當地一富豪鄉紳。

“先生今日在朝堂之事,我已聽說,在下對先生提到的函數執行過程中可中斷和恢復的技術頗有興趣,還請先生不吝賜教”,主人說完拜了一拜。

“賜教不敢當,我此次來Java帝國,所傳之道名叫協程,是一種高並發開發的絕技,可無奈貴國國君與大臣皆不識貨,無功而返,可惜啊,可惜!”,使者嘆息到。

 

 

“協程?這是何物?我只聽說過進程和線程,卻是從未聽過協程”

使者起身說到:“線程是操作系統抽象出來的執行流,由操作系統統一調度管理。那在一個線程中,同樣可以抽象出多個執行流,由線程來統一調度管理。這線程之上抽象的執行流就是協程”

主人有些不解,問到:“一個線程怎么會有多個執行流呢?”

“這便是我今日在朝堂上說的,線程執行函數遇到阻塞后,可以保存上下文后退出,轉而執行別處的代碼,這里就從一個執行流轉向了另外的執行流”,使者解釋到。

主人拍案而起,“原來是這個意思,妙哉,妙哉啊!不過,這線程是操作系統在調度管理,那線程里抽象出來的執行流,也就是協程,該怎么調度管理呢?操作系統可以通過時鍾中斷和系統調用進入內核來剝奪線程的執行權,那線程該如何剝奪協程的執行權來實現調度管理呢?”

 

 

“真是個好問題!線程的調度由操作系統來管理,是搶占式調度。而協程不同,協程需要互相配合,主動交出執行權,這也是協程的名字——協作式程序的來歷”

“主動交出執行權?如何辦到?”,主人追問。

“辦法有很多,比如C++帝國有一協程框架,名叫libco,他通過HOOK關鍵的系統函數來實現調度器的介入”

“那你們Golang是怎么做的?也是這樣嗎?”

“我們Golang帝國可不一樣,我們先天設計就是支持協程,系統調用都被我們封裝好了,應用程序調用時遇到需要阻塞的,像是文件讀寫Read/Write、Sleep我們的調度器就能有機會介入,去執行調度管理了”,使者得意的說到。

 

 

主人思考片刻,問到:“那我們Java該如何實現呢,還請先生賜教”

“你們Java語言,是通過JVM在執行,字節碼的執行都在JVM的掌控之中,要想實現對應用代碼執行流的中斷和恢復還不是易如反掌?”,使者說到。

主人點了點頭,若有所思。

新的征程

主人與使者交談甚歡,不知不覺已近黃昏。

主人起身說到:“今蒙先生賜教,大慰平生。還請先生在府上多留時日,我好細細請教。”

使者連連揮手,說到:“我還有要事在身,明日就要離去”

“不知先生欲往何處?”

“聽說C++帝國又要發布新版本,我打算前往傳道”

主人面露疑惑:“C++帝國不是有libco了嗎?”

“libco終究不是朝廷之物,此番前去,希望可以讓協程納入新的官方標准”

 

 

翌日清晨,使者拜別主人,策馬離去。

不久,Java帝國朝堂上傳來消息,民間有人推出了協程框架——Quasar,一時朝野震動。

往期TOP5文章

CPU明明8個核,網卡為啥拼命折騰一號核?

因為一個跨域請求,我差點丟了飯碗

完了!CPU一味求快出事兒了!

哈希表哪家強?幾大編程語言吵起來了!

一個HTTP數據包的奇幻之旅

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM