本質に迫る: Go WaitGroup の仕組みと内部実装を詳しく探る
WaitGroupはGo言語の並行同期機構であり、ゴルーチンのグループの完了を待機するために使用されます。3つの主要なメソッドであるAdd、Done、Waitを提供します。
WaitGroup に、待機する Goroutine 数を追加するのが Add メソッドです。Done メソッドは、Goroutine が終了したことを表すために、WaitGroup から待機中の Goroutine 数を 1 つ減らします。Wait メソッドは、すべての待機中の Goroutine が完了するまで呼び出し側の Goroutine をブロックさせます。
WaitGroup内部実装は主にカウンターと条件変数からなります。カウンターは未完了のgoroutine数を記録するために利用し、条件変数はgoroutineのブロックとウェイクアップを実現するために利用します。
WaitGroupの初期化時には、カウンターは0に設定され、条件変数も初期化されます。Addメソッドが呼び出されるたびに、カウンターは指定された数だけ増加します。Doneメソッドが呼び出されるたびに、カウンターは1減らされます。Waitメソッドが呼び出されると、カウンターが0より大きい場合は、現在のgoroutineはブロックされ、条件変数の通知を待ちます。カウンターが0に減少すると、待機していたすべてのgoroutineはウェイクアップされ、後続のコードの実行を続行します。
WaitGroupのカウンターは有符号整数なので負の値を取り得ることに注意してください。これは、場合によってはAddメソッドを使用してカウンターを増やしてもDoneメソッドを使用してカウンターを減らさない場合があるためです。この場合、カウンターは負の値になる可能性があります。カウンターが負の値の場合、Waitメソッドは現在のゴルーチンをブロックせずにただちに返ります。
つまり、WaitGroupはカウンタと条件変数の組み合わせによって、一連のgoroutineの完了を効率的に待つ、シンプルなメカニズムを実現しています。これはGo言語で一般的に使われる並行同期機構の1つであり、複数のgoroutineの並行実行を簡単に制御できます。