ホームページ  >  記事  >  バックエンド開発  >  phpコルーチンの詳しい説明(例付き)

phpコルーチンの詳しい説明(例付き)

不言
不言オリジナル
2018-09-20 17:41:325080ブラウズ

この記事では、PHP コルーチンの詳細な説明 (例付き) を提供します。一定の参考価値があります。必要な友人が参照できます。お役に立てれば幸いです。

マルチタスク (並列性と同時性)

コルーチンについて話す前に、マルチプロセス、マルチスレッド、並列性、および同時性について話しましょう。

シングルコア プロセッサの場合、マルチプロセス マルチタスクの原理は、オペレーティング システムが毎回特定の CPU タイム スライスをタスクに割り当て、その後割り込み、次のタスクに特定のタイム スライスを実行させることです。そしてまた中断し、次の作業に進む、というように続きます。

実行タスクの切り替えが非常に速いため、外部ユーザーには複数のタスクが同時に実行されているような印象を与えます。

マルチプロセスのスケジューリングは、オペレーティング システムによって実装されます。プロセス自体は、いつスケジュールされるかを制御できません。つまり、プロセスのスケジューリング は、外部の # によって実行されます。 ## スケジューラ プリエンプティブ 実装

コルーチンでは、他のタスクが実行を継続できるように、現在実行中のタスクが自動的に制御をスケジューラに戻す必要があります。これは、

プリエンプティブマルチタスクの正反対であり、プリエンプティブ マルチタスクのスケジューラは、自身の希望に関係なく、実行中のタスクを強制的に中断できます。プログラムが自動的に制御を引き継ぐだけであれば、悪意のあるプログラムが他のタスクと共有せずにすべての CPU 時間を簡単に占有してしまうでしょう。

コルーチンのスケジューリングはコルーチン自体によって実装されます

積極的に制御を外部スケジューラーに放棄しますxrange 関数を実装するジェネレーターの例に戻ります。実行プロセス全体の切り替えは、次の図で表すことができます。

コルーチンは、

純粋なユーザーモード スレッド

として理解でき、むしろ コラボレーションを通じてタスクの切り替えを実行します。先取りよりも。 プロセスやスレッドと比較すると、コルーチンのすべての操作はオペレーティング システムのカーネル モードではなくユーザー モードで完了でき、作成と切り替えのコストが非常に低くなります。

簡単に言えば、

Coroutine

は、現在のタスクの実行を中断し、現在のローカル変数を保存し、次回実行を継続するために現在のローカル変数を復元するメソッドを提供することです。 大きなタスクを複数の小さなタスクに分割し、順番に実行できます。システム IO を待機している小さなタスクがある場合は、それをスキップして次の小さなタスクを実行します。このようにして、スケジュールを戻すことができます。オペレーションと CPU 計算の並列実行により、一般にタスクの実行効率が向上します。これがコルーチンの意味です。

マルチスレッド

単一コアの下では、マルチスレッドを実行する必要があります。 concurrent;

ただし、統合プロセスの現在のマルチスレッドはマルチコア CPU で実行できるため、並列処理が可能です。

Concurrency (並行性)

は、次の機能を指します。複数の同時アクティビティを処理しますが、同時イベントは必ずしも同時に発生する必要はありません。

Parallel (Parallesim)

は、同時に発生する 2 つの同時イベントを指し、同時実行の意味がありますが、同時実行は必ずしも並列である必要はありません。

重複する期間内で複数の操作を実行できます。


並列処理と同時実行の違い

同時実行

はプログラムの構造を指し、並列はプログラムの状態を指します。 runningParallel
は同時実行である必要があります。Parallel同時実行設計の一種です 単一のスレッドが Parallel## に到達することはできません# state
Coroutine

Coroutine サポートは

generator

に基づいており、ジェネレーターにデータを送り返す機能が追加されています (呼び出し元は呼び出されたジェネレーター関数にデータを送信します)。

これにより、ジェネレーターから呼び出し元への一方向通信が、両者の間の双方向通信に変更されます。send メソッドについては前の記事ですでに説明しました。コルーチンについて理解しましょう
同期コード

非同期実行コードが関与する前のコードは次のようになります

function printNum($max, $caller)
{
    for ($i=0; $i<$max; $i++ ) {
        echo "调度者:" . $caller . "  打印:" . $i . PHP_EOL;
    }
}

printNum(3, "caller1");
printNum(3, "caller2");

# output
调度者:caller1  打印:0
调度者:caller1  打印:1
调度者:caller1  打印:2
调度者:caller2  打印:0
调度者:caller2  打印:1
调度者:caller2  打印:2

コルーチンを使用した後のコードの改善

初稿、ジェネレーターの実行を手動で調整します

# 本代码手动调整了进程执行代码的顺序,当然本代码实现不用协程也可以,只是利用本流程说明协程作用
# 生成器给了我们函数中断,协程[生成器send]给了我们重新唤起生成器函数的能力
function printNumWithGen($max)
{
    for ($i=0; $i<$max; $i++ ) {
        $res = yield $i;
        echo $res;
    }
}

$gen1 = printNumWithGen(3);
$gen2 = printNumWithGen(3);

// 手动执行caller1 再 caller2
$gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);
$gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);

// 手动执行caller1 再 caller2
$gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);
$gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);

// 手动执行caller2 再 caller1
$gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);
$gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);

# output
调度者: caller1 打印:0
调度者: caller2 打印:0
调度者: caller1 打印:1
调度者: caller2 打印:1
调度者: caller2 打印:2
调度者: caller1 打印:2

概要

上記のケースにより、コルーチンの設計の意味とコルーチンの使用方法を誰もが理解できるはずです。

次に、コルーチン用の自動スケジューラ (Co 自動実行プログラム) を自動的に作成しましょう。必要はありません。手動で中断して再開するには


以上がphpコルーチンの詳しい説明(例付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

関連記事

続きを見る