Goのゴルーチンの切り替えの仕組み
Go言語のgoroutine(ゴルーチン)は、Go言語ランタイムシステムによって管理される軽量スレッドのことです。goroutine間の切り替えは、Go言語のスケジューラーによって管理されます。
Goランタイムのスケジューラーは、「M:N」スケジューリングモデルを使用しており、M はオペレーティングシステム (OS) スレッドを表し、N はゴルーチンを表します。このスケジューラーは、複数のゴルーチンを少数の OS スレッドにマップすることで、ゴルーチンの同時実行を実現します。このモデルの利点は、限られた OS スレッドで多数のゴルーチンを実行して、同時実行パフォーマンスを向上させることができる点です。
スケジューラは、コルーチン間の切り替えを担当し、各コルーチンに実行機会を与える。このとき、スケジューラは、プリエンプティブ(先制)スケジューリングと呼ばれる手法を利用する。これは、コルーチンが長時間実行またはブロックされている場合に、スケジューラはコルーチンの実行を停止し、実行可能な別のコルーチンに切り替えることを意味する。
スレッドの切り替え中に、レジスタの状態を保存・復元することで、コルーチンのコンテキスト(プログラムカウンタ、スタックポインタなど)が保存されており、切り戻した際に前の実行ポイントから再開できる状態が保たれます。
注意すべきは、Golangのgoroutineは真の並行実行ではなく、スケジューラのgoroutine切り替えによって並行実行を模倣していることだ。1つのOSスレッド上で動作する複数のgoroutineは、スケジューラの调度によって順番に実行され、このような方法は並行実行と呼ばれる。そのため、goroutineの切り替えはコストの低い軽量切り替えとなり、大規模並行を効率よく実現できる。