Unity的協程使用起來比較方便,可是因爲其封裝和隱藏了太多細節,使其看起來比較神祕。好比協程是不是真正的異步執行?協程與線程究竟是什麼關係?本文將從語義角度來分析隱藏在協程背後的原理,並使用C++來實現一個簡單的協程,以揭開協程的神祕面紗。(文內代碼爲截圖,可點擊放大查看。)node
1、什麼是協程編程
簡單來講,協程是一個有多個返回點的函數。通常來講一個函數只有一個返回點,函數的調用者調用一次後,函數的生命週期就結束了。而對於協程來講,其生命週期由調用者來決定,能夠經過返回值來決定如何進行一次調用以及如何結束調用。閉包
因爲協程返回的是一系列的值,每個yield return對應一次返回。用迭代器做爲返回類型是比較好的選擇,能夠簡單的認爲每個yield return對於了迭代器中的一個元素。異步
Unity的C#代碼中一個協程的返回值一般是IEnumerator類型,IEnumerator 接口有兩個方法,分別是 Current 和 MoveNext。咱們能夠簡單的認爲:協程就是一個返回迭代器的函數,一開始迭代器的Current指向函數的開頭,每執行一次MoveNext,Current就指向下一個yield return 返回的值。例如:函數
2、協程的核心,神奇的yield線程
咱們來看看上而代碼示例中的函數coroutine:翻譯
上面代碼神奇的地方在於關鍵詞yield,爲何能夠調用屢次yield return返回一組值,而且該函數的返回值變成了Enumerator類型?這其實就是隱藏在協程背後的核心原理。有不少關於協程的核心原理的分析及實現的文章,大多都是從系統底層的角度來分析,使用了彙編,goto語句或者是C 語言的 setjmp 和 longjmp來實現了協程,雖然分析得比較透徹,但對讀者所掌握的知識要求比較高,其中的一些概念比較晦澀,難於理解。設計
實際上從語義角度來看,協程的工做原理比較簡單,任何支持閉包的語言均可以實現協程。下面咱們從語義的角度來解釋協程:orm
1.每個yield return被包裝成一個函數(簡稱爲Y函數),若是該函數使用了外層的局部變量,將造成一個閉包協程
2.Y函數的返回值爲yield傳入的對象和下一個yield return所包裝成的函數
3.對迭代器的MoveNext調用等價於對Y函數的調用
4.最後一個yield return包裝成的Y函數返回yield傳入的對象和一個空函數以表明迭代結束(即調用MoveNext時返回false)
3、簡單協程的C++實現
如下是根據協程在語義上的解釋,用C++的實現一個簡單協程示例:
一共不到60行代碼,就實現了簡單的協程。對於上示例中的coroutine函數,除了語法上有一些差別,語義已經和C#的協程徹底一協了,甚至咱們能夠引入一個宏讓其長得更像C#的協程,例如:
雖然以上代碼段看起來已經比較像Unity的協程了,可是遺憾的是代碼還不夠簡潔,有一點點語法噪音(函數的結尾部分多了一些沒意義的括號)語法也不夠統一(最後一行是return yield)。
4、For循環
第三節咱們講了協程的簡單的實現,可是若是咱們若是在for循環中使用yield還存在問題,好比如下代碼段:
coroutine1函數返回的迭代器中只包含一個值1,而不是咱們指望的1~10。所以對於協程中的循環咱們須要特殊處理。分析以上代碼,咱們指望的是對於循環中的每個i,調用yield生成一個coroutine node,而後將這些node合併成一個鏈表返回。所以咱們能夠將協程中的for語句翻譯成一個For函數,代碼以下:
Combine函數實現將兩個Coroutine Node鏈接在一塊兒合併成一個鏈表返回,其定義代碼以下:
有了For函數,能夠將coroutine1實現能夠改爲以下:
雖然在語法上該函數有一些醜,可是是從語義上徹底是等價如下C#代碼的:
如下是一個更加複雜的示例:
語義上等價的C#代碼爲:
5、總結
本文從語義的角度來解釋了協程的運行機制,並使用C++實現了簡單的協程,但仍有部份內容未討論到,好比怎樣在For循環中實現break,yield break等,其實要實現這些並不困難,感興趣的同窗能夠自行去研究。
回到引言中提到的兩個問題:
協程是否爲異步執行?嚴格意義上來說,協程並非異步執行的,可是調用者能夠分時間片去執行每個yield,讓程序看起來像是異步的。協程和線程是什麼關係?協程與線程之間沒有嚴格的對應關係,可是能夠結合使用,隱藏一些沒必要要的細節以簡化編程,好比unity的WWW。
來源:公衆號<Gad-騰訊遊戲開發者平臺>
做者:Tseclam
原題:程序|深刻淺出!從語義角度分析隱藏在Unity協程背後的原理
產品經理必讀文章
一份鵝廠產品經理自我成長的文檔
騰訊內部培訓手冊:產品經理晉升路上的那些坎兒
重磅乾貨|QQ運營女王:小白到大神,要跨過哪些坑
不聲不響我就當了產品經理......
騰訊產品法則:從需求分析到需求管理,作產品需求最全的方法都在這了
爲什麼有些產品經理畫的線框圖總被吐槽
什麼是「好產品」?
陳會華:寫給喜歡數據分析的初學者
體驗至上的時代,交互設計師能爲遊戲作點什麼?
熊一冬:作網遊不是開寶箱-產品運營大循環思