ミューテックスとセマフォの違い:排他制御と同期を比較

ミューテックスは、臨界区間を守り、共有の資源を同時に使えるスレッドを1つだけにします。ロックしたスレッドが、アンロックもしなければなりません。セマフォはカウンタで、限りのある資源を同時に使えるスレッドの数を制御し、あるスレッドから別のスレッドへの、イベントの通知にも使えます。ミューテックスは所有と排他、セマフォは数えることと通知のための仕組みです。

項目ミューテックスセマフォ
目的排他制御。臨界区間に入れるのは同時に1つのスレッドだけ計数。N個の資源のプールへのアクセスを制限する、またはスレッド間でイベントを通知する
値ロック中かアンロックか(2値)0以上の整数のカウント(0または1だけの場合が、バイナリセマフォ)
所有者ロックしたスレッドが持ち、そのスレッドがアンロックするべき所有者はいない。どのスレッドでもポストやシグナルを出せる
操作ロックとアンロックウェイト(P、減らす)とポスト(V、増やす)
スレッド間のシグナル想定していない使える。たとえば、生産者が消費者へ知らせる
優先度逆転優先度継承で避けられることが多い通常は対応していない
主な用途リストやカウンタなど、共有のデータ構造を守る接続プールの制限、容量に限りのある生産者・消費者のバッファ、割り込みハンドラからタスクへの通知
よくある落とし穴ロックの順序が一定でないことによるデッドロック、アンロックの忘れカウントが合わないことによる、シグナルの取りこぼしとデッドロック

数値は代表的な目安で、世代や製品によって異なります。

どんなときに使うか

ミューテックス
複数のスレッドが同じデータにさわり、同時に1つだけが許されるとき。
セマフォ
資源を使うスレッドの数を制限したいとき、または何かが起きたときにスレッドを起こしたいとき。

よくある質問

ミューテックスとバイナリセマフォは同じですか?

同じではありません。どちらも2つの状態を持ちますが、ミューテックスには所有者がいて、その所有者がアンロックする必要があり、優先度継承にも対応することが多いです。セマフォには所有者がなく、どのスレッドでもシグナルを出せます。

カウンティングセマフォが必要なのはどんなときですか?

N個の接続のプールなど、資源を使えるスレッドの数を制限したいとき、または、生産者・消費者のバッファで、使える要素の数を数えたいときです。

デッドロックとは何ですか?

スレッドが、互いに永久に待ち合う状態です。たとえば、スレッドAがロック1を持ってロック2を待ち、スレッドBがロック2を持ってロック1を待つ場合です。ロックを取る順序を一定にすると避けられます。

スピンロックとミューテックスの違いは何ですか?

スピンロックは、ビジーウェイトで待つので、マルチコアでの非常に短い待ちに向きます。ミューテックスは、待つスレッドをスリープさせるので、長い待ちに向きます。

理解度チェック

ミューテックス(眠って待つロック)とスピンロックを比べた説明として正しいものはどれか。

  1. Aミューテックスは待つ間CPUを手放すので長い待ちに向くが、眠ったり起きたりにOSの手間がかかる
  2. Bミューテックスは待つ間もCPUを使い続けるので、短い待ちにしか使えない
  3. Cミューテックスとスピンロックは同じもので、名前が違うだけである
答えと解説を見る

正解:A. ミューテックスは待つ間CPUを手放すので長い待ちに向くが、眠ったり起きたりにOSの手間がかかる

ミューテックスは、ロックが取れないとスレッドを待ち状態にしてCPUをほかのスレッドに譲り、ロックが解放されるとOSが起こします。待つ間にCPUをむだにしないので長い待ちに向きますが、眠る・起きる処理とコンテキストスイッチに数マイクロ秒ほどかかります。実際のライブラリのミューテックスは、少しだけスピンしてから眠るなど、両方の長所を組み合わせています。

カウンタ付きのセマフォの使い方として最も適切なものはどれか。

  1. A1つの変数の値を、必ず2倍にする
  2. Bプログラムの実行をすべて1つのスレッドにまとめる
  3. C同時に使える数が決まっている資源(例: 接続が4本まで)を、4つのスレッドまで同時に使わせる
答えと解説を見る

正解:C. 同時に使える数が決まっている資源(例: 接続が4本まで)を、4つのスレッドまで同時に使わせる

セマフォは、残りの数を表すカウンタを持ち、使う前に1減らし(0なら増えるまで待つ)、使い終わったら1増やします。初期値を4にすれば、同時に4つまでのスレッドが資源を使えます。初期値を1にすれば、ロックのように排他に使えます。待っているスレッドは眠らせてOSが起こすのが一般的です。

スピンロックの説明として正しいものはどれか。

  1. Aロックが空くまで、スレッドを眠らせてOSに起こしてもらう方式のロック
  2. Bロックが空くまで、ループでロックの変数を調べ続けて待つ方式のロック
  3. Cディスクを回転させてデータを守る仕組み
答えと解説を見る

正解:B. ロックが空くまで、ループでロックの変数を調べ続けて待つ方式のロック

スピンロックは、アトミック命令でロックを取ろうとし、取れなければすぐにもう一度試すことを繰り返します。OSを呼んで眠ったり起きたりする手間がないので、ロックを持つ時間がごく短い場合に速く動きます。OSのカーネルの中や、割り込みハンドラとの排他などでよく使われます。一方で、待っている間もCPUを使い続けるという欠点があります。

  1. デッドロックの例として正しいものはどれか。
  2. 読み書きロック(リーダー・ライターロック)の特徴として正しいものはどれか。
  3. 条件変数で「キューが空でなくなるまで待つ」とき、待ちから起きた後に条件をif文ではなくwhile文で確かめ直す理由として正しいものはどれか。

マルチコアと同期の練習問題へ

関連する用語の解説

ミューテックス
同時に1つのスレッドだけが持てるロック。取れないときはスレッドを眠らせてCPUを譲り、解放されるとOSが起こす実装が一般的。
セマフォ
残りの数を表すカウンタを持つ同期の仕組み。使う前に1減らし(0なら待つ)、使い終わったら1増やす。同時に使える数が決まった資源の管理に使う。
スピンロック
ロックが空くまで、ループでロックの変数を調べ続けて待つ方式のロック。待ちが短いときに速いが、待つ間もCPUを使い続ける。
デッドロック
複数のスレッドがそれぞれ資源を持ったまま、ほかのスレッドが持つ資源を待ち合い、誰も先に進めなくなる状態。ロックを取る順番を全体で決めて防ぐ。

関連する比較