セマフォ、 mutex、条件変数
記事の目的
掲題の3つの機構は特徴に似通っている部分があることもあり、それぞれの違いや使い分けについて混乱してきたので整理した。
まとめ
機構 | 用途 | |||
---|---|---|---|---|
相互排他 | 同期 | シグナル処理 | リソース管理 | |
Mutex | ✓ | - | - | - |
条件変数 | - | ✓ | - | - |
セマフォ | - | ✓ | ✓ | ✓ |
各用途の要件
上記表に出てくる各用途に必要な条件は以下の通り
排他
a.「未使用」「使用中」の2種類の表現
b. 現在の状態に基づいて判定
c. 「使用中」に設定したスレッド以外は「未使用」に戻せない
同期
a. 待つ対象の処理が終わったかどうかの判別が可能
シグナル処理
a. 対象のシグナルが送信されたことを検出可能
b. 複数のシグナルが送信されても読み飛ばさず対応可能
なお、シグナル処理の要件は同期を内包する(シグナル処理に使える機構は同期にも使えるが、逆は不可)
mutex
特徴
使い方:
- 使う時にロックする
- 使い終わったら戻す
すでにロック中だとロックできない。これにより排他制御を実現する。
なぜ条件変数は排他に使えない?
条件変数によって分かるのは「ある変数が特定の値になったか」なので、「今誰かが使っているか」は分からない。(要件aを満たさない)
なぜセマフォは排他に使えない?
セマフォは、値を増やす操作と減らす操作を行うのが同じスレッドである必要はない。つまり、他のスレッドからロックを解除できてしまう。(要件cを満たさない)
なぜ同期には使えない?
mutexは処理が終わったらロックを解除して値を戻してしまう。つまり、「ある処理が終わった」のか「そもそも始まっていない」のかの区別ができない。(要件aを満たさない)
例えば、スレッドAがBを待ちたい場合、
- Bがmutexをロック
- Aはmutexをロックしようとするがブロック
- Bがmutexをアンロック
- Aが処理開始
という処理フローを期待するが、もしAが先に始まってしまった場合、AはBを待たずに処理を継続できていしまう。
mutexはあくまで排他制御を目的としているため、このような設計になっている。
逆に上記の通り同期できるような仕組みでは排他制御はできない。
条件変数
使い方
- 待つ側は、シグナルを待つ
- 待たれる側は、処理を終えたらシグナルを送信
特徴
ある条件が満たされるまで待機する、という処理を効率よく行うために開発された。
whileなどによるボーリングはCPU時間を消費するが、条件変数はシグナルが来るまでスリープする。
課題
待ち始めた時にシグナル送信済みだと、永遠に起こされない。過去のシグナルを保存していないため。
→ 待ち始める前に、変数の値をチェックし、すでに条件が成立しているならシグナルを待たない。 mutexは、この変数が変えられないようにするために使用する。
なぜシグナルを保存しない?
あくまで開始の条件は「『今』それが満たされている」こと(レベルトリガ)。
過去のシグナルを保存していると、今条件を満たしていなくても処理が始まってしまう。
なぜシグナル処理に使えない?
複数回信号が送信されても拾えないため。レベルトリガだから、条件が満たされたことしか分からない。(要件bを満たさない)
混乱ポイント
- シグナル送信は効率よく待つための手段であって、イベントを検出するためではない。あくまで「今」条件が満たされていることは絶対。(シグナル送信だからイベントを検出していると勘違いして混乱した)
- mutexを使うのは条件変数をチェック前に変更されないためで、待ち合わせのためではない(なぜ2つの手段が必要なのか理解できなかった)
セマフォ
特徴
- セマフォの値を増やす操作と減らす操作
- セマフォは負の値をとれない。減らす操作を行った時点で0の場合、他の人が増やしてくれるまでブロック
「値が正になった」というイベントを検知するエッジトリガ。
使い方(同期)
- 0で初期化
-(待たれる側)待ちたい処理が終わったら1にする
-(待つ側)セマフォを減らす。0の間はブロックし、処理が終わって1になると進むことができる
使い方(シグナル処理)
- シグナルを受信したらセマフォを1増やす
- ワーカは、セマフォの値を減らす。
シグナルを受信した分だけセマフォの値が増えているので、それだけワーカが動ける。
複数のイベント、過去のイベントも取りこぼさず保存している。
条件変数との使い分け
「今」ある条件が満たされていることが重要ならば条件変数、ある処理が行われたことが重要ならばセマフォ。
例えばある処理の結果条件が満たされたとしても、その後その条件がまた変わってしまう可能性がある場合にはセマフォは不向き(今もその条件が成立しているのか不明)
Discussion