システムコールを超えたゴルーチンの降伏点
Go プログラムでは、ゴルーチンは同時実行のための主要なメカニズムです。 goroutine をブロックするシステムコールは既知のイールド ポイントですが、その他の考えられるイールド ポイントを考慮せずに goroutine のスケジューリングを理解することは完全ではありません。
疑われるイールド ポイントの 1 つは関数呼び出しです。関数呼び出しでは、スケジューラーがスタックをチェックする必要があるためです。成長。ただし、数学的演算のみを実行する場合、「ゴルーチンは、終了するか、他の実行に影響を与える可能性のある何かに到達するまで、スレッドをロックする」と述べられています。
これをテストするために、実行されるプログラムが作成されました。関数呼び出しのない 3 つのループ (メイン関数に 1 つ、別のゴルーチンに 2 つ)。プログラムは GOMAXPROCS を 1 に設定し、Go コードを同時に実行できる OS スレッドの数を制限します。ただし、出力には main 関数と goroutine からのインターリーブされたメッセージが依然として表示されており、関数呼び出しがなくても goroutine が制御を行うことを示唆しています。
この明らかな矛盾に対する答えは、Go 1.14 で導入された非同期プリエンプションにあり、これにより可能性が追加されます。ほぼどこでも先制ポイントを獲得できます。したがって、ゴルーチンは、システムコールをブロックする以外のさまざまなポイントで制御を譲ることができます。
プリエンプション ポイントの正確な実装は Go リリース間で変更される可能性がありますが、非同期プリエンプションにより、関数呼び出しのないループでスケジューラーがデッドロックしたり、ガベージが大幅に遅延したりすることがなくなります。コレクション。それにもかかわらず、非同期の配列書き込みと非アトミックなインデックス更新により、プログラムの動作に影響を与える可能性のある協調的なスケジューリング ポイントが導入される可能性があることに注意することが重要です。
以上がゴルーチンはシステムコールや関数呼び出しを超えた制御を実現しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。