引自我在知乎上的回答:進程 線程 協程 例程 過程 的區別是什麼? - 駿馬金龍的回答 - 知乎shell
首先解釋下程序、進程、上下文切換和線程。而後再解釋協程、例程、過程。編程
程序:源代碼堆起來的東西。至關於一個一動不動沒有生命的機器人。bash
進程:程序在系統上跑起來(運行)以後的東西(動態的)。至關於有了生命的機器人。生命是內核給的,動起來的能力是CPU提供的驅動力。多線程
上下文切換:在某一時刻,一核CPU只能執行一個進程。至關於內核只能讓一核CPU爲一個機器人提供驅動力讓它動起來(1:1),多核CPU能夠同時爲多個機器人提供驅動力。併發
線程:一個進程內能夠有多個執行線程,或者說線程是進程內部的小型進程。至關於在機器人內部根據機器人自身克隆了不少個基本徹底相同的體內小機器人。編程語言
如今,對比一下多進程和多線程?函數
而後是協程、例程、過程。可是在解釋這個以前,先解釋下如今更爲俗知的函數,以及它們和進程、線程之間的關係。oop
函數:一種代碼段。用來表示一個要完成的任務單元。固然,這個任務裏可能也包含了其它多個子任務。操作系統
先總結一下重點:進程、線程是機器人,函數是機器人要乾的活。線程
機器人是怎麼執行函數的呢?在不使用coroutine(也就是國人翻譯後的"協程")的狀況下,它的執行流程是固定的:從main函數開始,跳轉執行其它函數A,main函數被擱置等待,它必須等待跳轉後的函數A執行完返回後才能回到main函數繼續向下執行,若是函數A中還有調用函數B,那麼函數A被擱置等待,它必須等待函數B執行完返回後才繼續向下執行。直到main函數也執行完,程序退出。
繼續用機器人來比喻,那就是機器人要執行一個任務,但這個任務中要求臨時去執行另外一個任務,那麼這個機器人必須先去執行另外一個任務,並只能在執行完另外一個任務的時候回到以前的那個任務繼續執行。
因此,重點是:函數A中在第X行開始跳轉調用函數B時,函數A必須等待函數B執行完返回後才能繼續從第X行處開始繼續向下。
回到正題要解釋的東西:協程、例程、過程。
很遺憾,例程、過程、子程序,它們都是函數的不一樣稱呼,不一樣的時代、不一樣的編程語言稱呼的方式不同,都是任務單元。甚至面向對象裏的方法也是函數,只不過在面向對象的面具之下,它有一些和麪向對象相關的特性。
最後是協程。我猜你說的協程應該是coroutine這類東西,全稱是cooperative routine,也叫作cooperative tasks。只看英文的話,意思已經很明顯了:協同運行的子程序(子程序就是例程、函數、過程)。或者說是協同執行的任務。
在解釋coroutine以前,多插一句嘴。
coroutine被翻譯爲協程,我的認爲是不太合理的。在shell中有coproc的概念(ksh/bash等一些shell都支持coproc的功能),cooperative process,表示協同運行的進程,按單詞字面意思,這才應該被翻譯爲協程。
協同運行?這是個什麼意思。回顧下剛纔解釋函數(由於是co routine,因此我下面所有用routine來替換函數的說法)的執行流程在理解協同運行是什麼意思。
在正常狀況下,routine跳轉運行後必須原地等待跳轉後的那個routine執行完返回才能繼續從原地向下執行。
可是,使用coroutine的時候,假設routine1和coroutine2互爲coroutine,那麼routine1跳轉到routine2去執行的時候,它會等待routine2才能繼續向下執行,可是不必定是等待routine2執行完,也多是等待routine2從新跳轉回routine1(由於routine2已經產生了一些可讓routine1繼續運行的數據,而不是讓routine1繼續在那裏阻塞)。同理routine2也可能會原地等待routine1,routine1再跳回routine2。
可是這怎麼行,來來回回的跳轉總得退出吧?這就是跟所寫的代碼有關係了。好比某個routine中加入一個判斷,達到某一條件時就再也不跳轉,而是直接向下執行。
機器人的比喻又來了。機器人要執行一個任務,但要求臨時去執行另外一個任務,如今不強制規定必須執行完另外一個任務纔回來執行原始任務,而是能夠在執行另外一個任務的時候,又臨時回來執行原始任務。
若是說很差理解,那麼下面這個wiki中給的生產者消費者模型的僞代碼很容易幫助理解coroutine,這個程序不必定合理,但很是適合於理解"協同"的意義。其中q
是一個隊列,生產者coroutine會跳轉到消費者coroutine,同理消費者coroutine也同樣會跳轉到生產者coroutine。
var q := new queue coroutine produce loop while q is not full create some new items add the items to q yield to consume coroutine consume loop while q is not empty remove some items from q use the items yield to produce
這就是協同運行以及coroutine的解釋,我想應該已經不難理解了。
最後,說一下coroutine的優勢:
實際上,coroutine能夠認爲是單線程多任務的工做方式(固然,進程中實現coroutine也是能夠的),由於它在單個線程中的多個任務之間直接跳轉,而多線程是經過上下文切換來實現多任務的。換句話說,coroutine提供了併發卻不併行的功能。經過coroutine,還能實現更爲"實時"的上下文任務,由於coroutine之間的跳轉切換不須要任何系統調用和可能的阻塞調用,不須要像多線程同樣爲了線程之間的資源同步而使用額外的互斥鎖、信號量等。