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