摘要:協程協程就是用戶態的線程要理解是什么是用戶態的線程,必然就要先理解什么是內核態的線程。記住,不是協程,而是協程需要借助的特性來實現。
協程
“協程”就是用戶態的線程關于“用戶態線程”,我們用個小例子來加深理解要理解是什么是“用戶態的線程”,必然就要先理解什么是“內核態的線程”。 內核態的線程是由操作系統來進行調度的,在切換線程上下文時,要先保存上一個線程的上下文,然后執行下一個線程,當條件滿足時,切換回上一個線程,并恢復上下文。 協程也是如此,只不過,用戶態的線程不是由操作系統來調度的,而是由程序員來調度的,是在用戶態的 -- 摘自鏈接描述
我們有兩個函數 task1,task2,我們來手動調度它們的執行順序,比如在task1執行一半的時候去執行task2,兩個或者多個函數之間交替執行(這就是協程的概念)。
我們來個正常的函數調用方式:
可想而知,以上的輸出肯定是:
task1函數 執行第1 task1函數 執行第2 task2函數 執行第1 task2函數 執行第2但是我想在程序輸出task1函數 執行1之后就輸出task2函數 執行1怎么辦?
這個時候 yield 就派上用場了,PHP里的協程是需要借助 yield 來完成的。記住,yield 不是協程,而是協程需要借助 yield 的特性來實現。
current(); $task2->current();以上輸出:
task1函數 執行1 task2函數 執行1很好,以上結果達到了我們的預期。但是怎么讓函數里的代碼往下執行呢?
調用生成器的next方法:
$task1->next(); $task2->next();最后你將看到的輸出結果是兩個函數交替執行輸出的:
task1函數 執行1 task2函數 執行1 task1函數 執行2 task2函數 執行2小段總結以上的代碼實現可以抽象出兩個概念,任務和調度,任務就是task函數,調度就是我們怎么去調用這些task函數
調度器和任務生成器上一個小段總結里有兩個概念叫任務和調度,我們簡單的封裝個任務生成器和調度器
// 任務生成器 $createTask = (function () { $tasks = []; return function ($callback) use (&$tasks) { $task = [ "task" => $callback(), "id" => count($tasks) + 1, ]; array_push($tasks, $task); return $task; }; })(); // 調度器 function schedule($tasks) { $first = []; while (!empty($tasks)) { $task = array_shift($tasks); if (!array_key_exists($task["id"], $first)) { $first[$task["id"]] = true; $task["task"]->current(); } else { $task["task"]->next(); } if (!$task["task"]->valid()) { unset($tasks[$k]); } else { array_push($tasks, $task); } } }使用
$tasks = [ $createTask(function () { echo "任務1 執行第1次 "; yield; echo "任務1 執行第2次 "; }), $createTask(function () { echo "任務2 執行第1次 "; yield; echo "任務2 執行第2次 "; }) ]; schedule($tasks);輸出結果:
任務1 執行第1次 任務2 執行第1次 任務1 執行第2次 任務2 執行第2次可以從結果看出,調度器已經實現了多個任務之間進行協作。
網絡請求現在有個需求!就是任務在遇到網絡請求的時候,我們無需等待網絡請求的響應結果,而是遇到網絡請求的時候,把這個任務掛起,然后去執行其它任務,等網絡請求收到響應結果了再通知我們處理這時候需要我們用到非阻塞IO調用相關技術,涉及到系統內核層面,想了解可以點擊鏈接描述
在PHP里我們需要安裝個擴展eio,大家自行安裝
pecl install eio編碼:
$tasks = [ $createTask(function () { echo "任務1 執行第1次 "; yield; echo "任務1 執行第2次 "; }), $createTask(function () { echo "任務2 執行第1次 "; eio_custom(function () { return file_get_contents("https://segmentfault.com/"); }, EIO_PRI_DEFAULT, function ($data, $ret) { echo "請求完成 "; }); yield; echo "任務2 執行第2次 "; }) ]; schedule($tasks); eio_event_loop();在任務2 執行第1次的時候,遇到網絡請求,我們把請求任務交給系統內核,然后切換到其它任務去,等請求任務完成后回調我們傳入的函數。
輸出結果:
任務1 執行第1次 任務2 執行第1次 任務1 執行第2次 任務2 執行第2次 任務2 執行第1次的請求完成完!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/29283.html
摘要:為語言提供了強大的協程編程模式。提供的協程語法借鑒自,在此向開發組致敬協程可以與很好地互補。并發執行使用創建協程,可以讓和兩個函數變成并發執行。協程需要拿到請求的結果。 Swoole4為PHP語言提供了強大的CSP協程編程模式。底層提供了3個關鍵詞,可以方便地實現各類功能。 Swoole4提供的PHP協程語法借鑒自Golang,在此向GO開發組致敬 PHP+Swoole協程可以與...
摘要:協程完全有用戶態程序控制,所以也被成為用戶態的線程。目前支持協程的語言有很多,例如等。協程之旅前篇結束,下一篇文章我們將深入分析原生協程部分的實現。 寫在最前 ??Swoole協程經歷了幾個里程碑,我們需要在前進的道路上不斷總結與回顧自己的發展歷程,正所謂溫故而知新,本系列文章將分為協程之旅前、中、后三篇。 前篇主要介紹協程的概念和Swoole幾個版本協程實現的主要方案技術; 中篇主...
摘要:搶占式調度我們在今年年初就計劃實現的搶占式調度,以滿足實現有些場景下的不均衡調度帶來的問題。考慮開線程,負責檢查當前執行協程執行時間。達到我們的第二個協程主動搶占第一個協程的效果。 前言 Swoole內核團隊開設的專欄,會逐漸投入精力寫文章介紹Swoole的開發歷程,實現原理,應用實踐等,大家可以更好的交流,共同學習,建設PHP生態。 協程調度 去年Swoole推出了4.0版本后,完整...
摘要:如果僅依靠程序自動交出控制的話,那么一些惡意程序將會很容易占用全部時間而不與其他任務共享。多個操作可以在重疊的時間段內進行。 PHP下的異步嘗試系列 如果你還不太了解PHP下的生成器,你可以根據下面目錄翻閱 PHP下的異步嘗試一:初識生成器 PHP下的異步嘗試二:初識協程 PHP下的異步嘗試三:協程的PHP版thunkify自動執行器 PHP下的異步嘗試四:PHP版的Promise ...
摘要:線程擁有自己獨立的棧和共享的堆,共享堆,不共享棧,線程亦由操作系統調度標準線程是的。以及鳥哥翻譯的這篇詳細文檔我就以他實現的協程多任務調度為基礎做一下例子說明并說一下關于我在阻塞方面所做的一些思考。 進程、線程、協程 關于進程、線程、協程,有非常詳細和豐富的博客或者學習資源,我不在此做贅述,我大致在此介紹一下這幾個東西。 進程擁有自己獨立的堆和棧,既不共享堆,亦不共享棧,進程由操作系...
閱讀 1039·2021-11-18 13:23
閱讀 746·2021-11-08 13:16
閱讀 856·2021-10-11 10:58
閱讀 3511·2021-09-22 15:26
閱讀 1732·2021-09-08 10:42
閱讀 1807·2021-09-04 16:45
閱讀 1734·2019-08-30 15:54
閱讀 2565·2019-08-30 13:45