TL;DR

スレッド間の同期を行う仕組みの 1 つで、特定の条件が満たされるまでスレッドを待機させる。この待機をパーキングと呼ぶ。

なぜ必要か

ミューテックスと組み合わせて使うことで、共有リソースへの安全なアクセスを制御できる。ミューテックスだけでは「条件が満たされるまで待つ」ことを表しにくいが、条件変数を使えば、待つ側は通知が来るまで眠り、条件を満たした側が待っている側を起こせる。

仕組み

Go では sync.Cond で条件変数を使える。主なメソッドは次の 3 つである。

  • Wait(): 関連付けられたロックを解放して待機する。他のゴルーチンが Signal() か Broadcast() で通知すると、ロックを取得し直して処理を再開する
  • Signal(): Wait() でブロックしているゴルーチンがあれば、そのうち 1 つを再開させる
  • Broadcast(): Wait() で待機しているすべてのゴルーチンを再開させる

注意点

Wait() でのミューテックスの解放とゴルーチンの一時停止は、アトミックに行われる。

Broadcast() ですべてのゴルーチンを起こしても、ミューテックスを取得できるのは 1 つだけである。残りのゴルーチンは、そのゴルーチンがミューテックスを解放するまで取得待ちのままになる。

関連

出典