coroutine php PHP 協程實現

2021-10-22 21:15:46 字數 2025 閱讀 6893

多程序/執行緒

最早的伺服器端程式都是通過多程序、多執行緒來解決併發io的問題。程序模型出現的最早,從unix 系統誕生就開始有了程序的概念。最早的伺服器端程式一般都是 accept 乙個客戶端連線就建立乙個程序,然後子程序進入迴圈同步阻塞地與客戶端連線進行互動,收發處理資料。

多執行緒模式出現要晚一些,執行緒與程序相比更輕量,而且執行緒之間共享記憶體堆疊,所以不同的執行緒之間互動非常容易實現。比如實現乙個聊天室,客戶端連線之間可以互動,聊天室中的玩家可以任意的其他人發訊息。用多執行緒模式實現非常簡單,執行緒中可以直接向某乙個客戶端連線傳送資料。而多程序模式就要用到管道、訊息佇列、共享記憶體等等統稱程序間通訊(ipc)複雜的技術才能實現。

最簡單的多程序服務端模型

$serv = stream_socket_server("tcp:", $errno, $errstr)

or die("create server failed");

![image.png](

while(1) elseif (key($this->_batch) !== null) else else else else else else else else {

$this->iopoll(0);

yield;

* $scheduler = new scheduler;

* $scheduler->newtask(web server generator);

* $scheduler->withiopoll()->run();

* 新建 web server 任務後先執行 withiopoll() 將 iopolltask() 作為任務入隊

* @return $this

public function withiopoll()

$this->newtask($this->iopolltask());

return $this;

這個版本的 scheduler 裡加入乙個永不退出的任務,並且通過 stream_select 支援的特性來實現快速的來回檢查各個任務的 io 狀態,只有 io 完成的任務才會繼續執行,而 io 還未完成的任務則會跳過,完整的**和例子可以戳這裡。

也就是說任務交替執行的過程中,一旦遇到需要 io 的部分,排程器就會把 cpu 時間分配給不需要 io 的任務,等到當前任務遇到 io 或者之前的任務 io 結束才再次排程 cpu 時間,以此實現 cpu 和 io 並行來提公升執行效率,類似下圖:

image.png

單任務改造

如果想將乙個單程序任務改造成併發執行,我們可以選擇改造成多程序或者協程:

多程序,不改變任務執行的整體過程,在乙個時間段內同時執行多個相同的**段,排程權在 cpu,如果乙個任務能獨佔乙個 cpu 則可以實現並行。

協程,把原有任務拆分成多個小任務,原有任務的執行流程被改變,排程權在程序自己,如果有 io 並且可以實現非同步,則可以實現並行。

多程序改造

image.png

協程改造

image.png

協程(coroutines)和 go 協程(goroutines)

php 的協程或者其他語言中,比如 python、lua 等都有協程的概念,和 go 協程有些相似,不過有兩點不同:

go 協程意味著並行(或者可以以並行的方式部署,可以用 runtime.gomaxprocs() 指定可同時使用的 cpu 個數),協程一般來說只是併發。

go 協程通過通道 channel 來通訊;協程通過 yield 讓出和恢復操作來通訊。

go 協程比普通協程更強大,也很容易從協程的邏輯復用到 go 協程,而且在 go 的開發中也使用的極為普遍,有興趣的話可以了解一下作為對比。

結束個人感覺 php 的協程在實際使用中想要徒手實現和應用並不方便而且場景有限,但了解其概念及實現原理對更好的理解併發不無裨益。

如果想更多的了解協程的實際應用場景不妨試試已經大名鼎鼎的 swoole,其對多種協議的 client 做了底層的協程封裝,幾乎可以做到以同步程式設計的寫法實現協程非同步 io 的效果。

參考關注 newtonio - 創造者們的技術與工具

image.png

coroutine php PHP 協程實現

多程序 執行緒 最早的伺服器端程式都是通過多程序 多執行緒來解決併發io的問題。程序模型出現的最早,從unix 系統誕生就開始有了程序的概念。最早的伺服器端程式一般都是 accept 乙個客戶端連線就建立乙個程序,然後子程序進入迴圈同步阻塞地與客戶端連線進行互動,收發處理資料。多執行緒模式出現要晚一...

協程巢狀協程

import asyncio import functools 第三層協程 async def test1 print 我是test1 await asyncio.sleep 1 print test1已經睡了1秒 await asyncio.sleep 3 print test1又睡了3秒 ret...

9 協程 協程理論

本節的主題是基於單執行緒來實現併發,即只用乙個主線程 很明顯可利用的cpu只有乙個 情況下實現併發,為此我們需要先回顧下併發的本質 切換 儲存狀態 ps 在介紹程序理論時,提及程序的三種執行狀態,而執行緒才是執行單位,所以也可以將上圖理解為執行緒的三種狀態cpu正在執行乙個任務,會在兩種情況下切走去...