TL;DR
スレッド間の同期を行う仕組みの 1 つで、特定の条件が満たされるまでスレッドを待機させる。この待機をパーキングと呼ぶ。
なぜ必要か
ミューテックスと組み合わせて使うことで、共有リソースへの安全なアクセスを制御できる。ミューテックスだけでは「条件が満たされるまで待つ」ことを表しにくいが、条件変数を使えば、待つ側は通知が来るまで眠り、条件を満たした側が待っている側を起こせる。
仕組み
Go では sync.Cond で条件変数を使える。主なメソッドは次の 3 つである。
Wait(): 関連付けられたロックを解放して待機する。他のゴルーチンがSignal()かBroadcast()で通知すると、ロックを取得し直して処理を再開するSignal():Wait()でブロックしているゴルーチンがあれば、そのうち 1 つを再開させるBroadcast():Wait()で待機しているすべてのゴルーチンを再開させる
注意点
Wait() でのミューテックスの解放とゴルーチンの一時停止は、アトミックに行われる。
Broadcast() ですべてのゴルーチンを起こしても、ミューテックスを取得できるのは 1 つだけである。残りのゴルーチンは、そのゴルーチンがミューテックスを解放するまで取得待ちのままになる。