コルーチンとは何ですか?それらは同時実行性とどのように関連していますか?
13 に答える
コルーチンと並行性はほぼ直交しています。コルーチンは一般的な制御構造であり、フロー制御は2つの異なるルーチン間で協調して渡されます。
Pythonの「yield」ステートメントは良い例です。コルーチンを作成します。'yield'が検出されると、関数の現在の状態が保存され、呼び出し元の関数に制御が戻されます。その後、呼び出し元の関数は実行をyielding関数に戻すことができ、その状態は「yield」が検出されたポイントに復元され、実行が続行されます。
「 Luaでのプログラミング」の「Coroutines
」セクション から:
コルーチンは (マルチスレッドという意味で) スレッドに似ています。コルーチンは、独自のスタック、独自のローカル変数、および独自の命令ポインターを持つ実行ラインです。ただし、グローバル変数と他のほとんどすべてを他のコルーチンと共有します。スレッドとコルーチンの主な違いは、概念的に (マルチプロセッサ マシンでは文字どおり)、スレッドを含むプログラムは複数のスレッドを並行して実行することです。一方、コルーチンは協調的です。いつでも、コルーチンを含むプログラムはそのコルーチンの 1 つだけを実行しており、この実行中のコルーチンは、明示的に一時停止を要求した場合にのみ実行を一時停止します。
要点は次のとおりです。コルーチンは「共同」です。マルチコア システムでも、一度に実行されるコルーチンは 1 つだけです (ただし、複数のスレッドを並行して実行できます)。コルーチン間に非プリエンプティブがあり、実行中のコルーチンは明示的に実行を放棄する必要があります。
" concurrency
" については、Rob Pike のスライドを参照してください。
同時実行性は、独立して実行される計算の構成です。
そのため、コルーチン A の実行中に、コルーチン B に制御が渡されます。その後、しばらくして、コルーチン B が制御をコルーチン A に戻します。コルーチン間には依存関係があり、それらはタンデムで実行する必要があるため、2 つのコルーチンは同時実行ではありません。
コルーチンは特別な種類のサブプログラムです。従来のサブプログラムに存在する、呼び出し元と呼び出されたサブプログラムの間の主従関係ではなく、呼び出し元と呼び出されたコルーチンはより公平です。
コルーチンは、複数のエントリを持ち、それ自体を制御するサブプログラムです。Lua で直接サポートされています。
対称制御とも呼ばれます: 呼び出し元と呼び出されたコルーチンは、より対等な基準に基づいています
コルーチン呼び出しは履歴書と呼ばれます
コルーチンの最初の再開は先頭までですが、後続の呼び出しは、コルーチンで最後に実行されたステートメントの直後に開始されます
コルーチンは相互に繰り返し再開します。おそらく永遠に続きます
コルーチンは、プログラム単位 (コルーチン) の準同時実行を提供します。それらの実行はインターリーブされますが、オーバーラップされません
Python コルーチンから:
Python コルーチンの実行は、多くのポイントで中断および再開できます (コルーチンを参照)。コルーチン関数の本体内では、await および async 識別子は予約済みのキーワードになります。await 式、async for および async with は、コルーチン関数本体でのみ使用できます。
コルーチンから(C++20)
コルーチンは、後で再開 するために実行を一時停止できる機能です。コルーチンはスタックレスです。呼び出し元に戻ることで実行を中断します。これにより、非同期で実行されるシーケンシャル コード (明示的なコールバックなしで非ブロッキング I/O を処理するなど) が可能になり、遅延計算された無限シーケンスやその他の使用に関するアルゴリズムもサポートされます。
他の人の答えと比較してください:
私の意見では、再開された後半部分は、@Twinkle のように、コアの違いです。
ドキュメントの多くのフィールドはまだ進行中ですが、この部分は @Nan Xiao を除いてほとんどの回答と似ています
一方、コルーチンは協調的です。いつでも、コルーチンを含むプログラムはそのコルーチンの 1 つだけを実行しており、この実行中のコルーチンは、明示的に一時停止を要求した場合にのみ実行を一時停止します。
Program in Lua からの引用なので、おそらく言語関係(今はLuaに慣れていない)で、すべてのドキュメントがその一部だけを言及しているわけではありません。
同時実行との関係:コルーチン (C++20)
の「実行」部分があります。ここで引用するには長すぎます。
詳細の他に、いくつかの状態があります。
When a coroutine begins execution
When a coroutine reaches a suspension point
When a coroutine reaches the co_return statement
If the coroutine ends with an uncaught exception
When the coroutine state is destroyed either because it terminated via co_return or uncaught exception, or because it was destroyed via its handle
@ user217714の回答の下にある@ Adam Aroldからのコメントとして。並行性です。
しかし、マルチスレッドとは異なります。
std::thread から
スレッドを使用すると、複数の関数を同時に実行できます。スレッドは、関連付けられたスレッド オブジェクトが構築されるとすぐに実行を開始し (OS スケジューリングの遅延を保留します)、コンストラクター引数として提供される最上位関数から開始します。最上位関数の戻り値は無視され、例外をスローして終了する場合は、std::terminate が呼び出されます。トップレベル関数は、std::promise を介して、または共有変数を変更することによって、その戻り値または例外を呼び出し元に伝えることができます (同期が必要な場合があります。std::mutex および std::atomic を参照してください)。
並行性であるため、特に (OS の観点から) 待機が避けられない場合は、マルチスレッドのように機能します。これが混乱の原因でもあります。
まだ混乱している場合は、 a を理解するための非常に簡単な方法を次に示しますco-routine
。まず、 とは何routine
ですか?素人の言葉で言えば、ルーチンとは、私たちが何度も行うものです (たとえば、朝のルーチン)。同様に。プログラミング言語では、aroutine
は繰り返し使用するコードの一部ですa function
。ここで、a の一般的な特性を見るとfunction or routine
(注: これら 2 つの用語を慎重に同じ意味で使用しています)、関数が結果を出力する必要がある限り、いくつかの入力が必要であり、CPU スレッドを占有します。つまり、functions or routines
コード内の呼び出しをブロックしています。ただし、co-routine
同時に他のルーチンと共存できる特別な種類のルーチン (コルーチンという単語の「co」部分はこれに由来します) であり、非同期プログラミングの助けを借りてプログラミング言語でこれを実現できます。非同期プログラミングでは、1 つのコルーチンが何かが起こるのを待っているとき (ディスク io など)、もう 1 つのコルーチンが動作を開始し、このコルーチンが待機状態にあるとき、もう 1 つのコルーチンが最終的にアクティブになります。コードの待ち時間を短縮します。
上記を理解したら、Python でコルーチン関数を作成する方法を見てみましょう。次のようにコルーチン関数を定義できます-
async def my_coroutine_function():
return 123
そして、await
コルーチンの前に追加することで、上記のコルーチンを呼び出すことができます-
my_result = await my_coroutine_function()
結論として、
テレビ番組を見ているときに広告が表示されるとすぐに、携帯電話を持って友人にテキスト メッセージを送信します。これが非同期プログラミングです。テレビ番組 (コルーチン) が待機状態にある間に、他のコルーチン (友人にテキスト メッセージを送信) をアクティブにしました。