經過swoole協程入門,瞭解到協程的基本寫法。
更準確一點,是獨立、無執行順序的任務。
那有依賴關係或者執行順序有關的任務怎麼辦呢?
靠channel了!php
與容量有關
若是channel未滿,push不阻塞,若是已滿,push讓出控制流;
若是channel爲空,pop讓出控制流segmentfault
<?php // 設置一個容量爲50的channel $chan = new \Swoole\Coroutine\Channel(50); function t4(\Swoole\Coroutine\Channel $chan) { Co::sleep(0.005); #1 $chan->push([__METHOD__=>__LINE__]); #2 } function t5(\Swoole\Coroutine\Channel $chan) { Co::sleep(0.005); #3 $chan->push([__METHOD__=>__LINE__]); #4 } function t6(\Swoole\Coroutine\Channel $chan) { Co::sleep(0.005); #5 $chan->push([__METHOD__=>__LINE__]); #6 } go("t4", $chan); go("t5", $chan); go("t6", $chan); // cousume協程:c1 go(function() use($chan) { // chan元素個數 $chanNum = 3; // chan有數據時 while($chanNum>0) { #7 $item = $chan->pop(); #8 var_dump($item); #9 $chanNum --; } });
3個生產者協程(t4/t5/t6),1個消費者協程(用c1描述)
#1 t4遇到Co::sleep,讓出控制流,掛起;
#3 t5,相似於t4,掛起
#5 t6,相似於t4,掛起
#7 c1開始執行,while循環爲真,執行channel::pop()
#8 可能狀況:channel爲空,c1讓出控制流,掛起;
#8 可能狀況:channel非空,pop彈出數據,while循環繼續
若是while循環爲假,c1執行結束
若是while循環爲真,進入channel::pop()流程
...5ms後...
t4恢復執行(t4/t5/t6 sleep時間相同,所以都有可能先恢復執行,但同時只能有一個恢復,爲描述簡單以t4爲例)
#2 t4寫入channel數據,此時channel非空
#8 若是有消費者協程,控制流發生變化,消費者協程c1恢復執行(思考:若是c1的while循環爲假已經結束,會發生什麼呢?)
c1協程運行直到讓出控制流或者結束;
控制流回到t4協程,t4協程沒有後續代碼,執行結束;(問題:控制流有可能回到其餘協程t5/t6嘛?仍是必定會回到t4協程)
t5(t6)恢復執行,流程相似於t4的執行流程swoole
channel的容量很重要,太小的容量致使生產者自動讓出控制流而不能執行;
消費者,須要判斷生產者個數,來肯定循環次數或循環結束邊界,若是判斷錯誤(過小,致使channel數據未消費;太大,消費者會讓出控制流),會帶來意外的結果。code
回到文章的開頭,好像咱們是想介紹有依賴關係、調用順序的任務怎麼寫?
你確定已經猜到了,那就是先導任務放在生產者協程,後續任務放在消費者協程
經過channel的機制,保障任務的前後執行順序協程
channel解決了協程間通訊的問題,同時也提供了一種任務調度的方式。get