swoole協程之channel

前言

經過swoole協程入門,瞭解到協程的基本寫法。
更準確一點,是獨立、無執行順序的任務。
那有依賴關係或者執行順序有關的任務怎麼辦呢?
靠channel了!php

Channel特色

與容量有關
若是channel未滿,push不阻塞,若是已滿,push讓出控制流;
若是channel爲空,pop讓出控制流segmentfault

看例子:depend_co.php

<?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

相關文章
相關標籤/搜索