ミューテックスは、複数のスレッド間の競合状態を回避するために使用されます。
一方、セマフォは、複数のプロセスで使用される同期要素として使用されます。
あるプロセスがセマフォを待機している間、他のプロセスがセマフォを解放するため、ミューテックスをバイナリセマフォに置き換えることはできません。ミューテックスの場合、取得と解放の両方が同じで処理されます。
Mutex と Binary-Semaphore についてお話します。明らかにミューテックスを使用して、あるスレッドのデータが別のスレッドによって同時にアクセスされるのを防ぎます。
(lock() を呼び出したばかりで、データにアクセスしていると仮定します。つまり、他のスレッド (または同じスレッド コードの別のインスタンス) が、ロックされた同じデータにアクセスすることは期待できません。つまり、同じスレッド コードが別のスレッド インスタンスで実行され、ロックにヒットした場合、lock() は制御フローをブロックする必要があります。)
これは、同じデータにアクセスし、同じミューテックスによってロックされている別のスレッド コードを使用するスレッドに適用されます。
この場合、まだデータにアクセスしている途中であり、ミューテックスのロック解除に到達するまでにさらに 15 秒かかる場合があります (ミューテックス ロックでブロックされている他のスレッドのブロックが解除され、コントロールがアクセスできるようになるため)。データにアクセスします)。
別のスレッドが同じミューテックスのロックを解除することを許可し、そのミューテックス ロックで既に待機 (ブロック) しているスレッドがブロックを解除してデータにアクセスできるようにしたことがありますか? (私がここで言っていることを理解していただければ幸いです。)
合意された普遍的な定義に従って、
- 「ミューテックス」では、これは起こりません。他のスレッドはあなたのスレッドのロックを解除できません
- 「バイナリセマフォ」を使用すると、これが発生する可能性があります。他のスレッドは、スレッド内のロックを解除できます
したがって、mutex の代わりにバイナリ セマフォを使用することに非常にこだわっている場合は、ロックとロック解除の「スコープ」に非常に注意する必要があります。つまり、すべてのロックにヒットするすべての制御フローがロック解除呼び出しにヒットし、さらに「最初のロック解除」はなく、常に「最初のロック」であるべきです。
トイレの例
ミューテックス:
トイレの鍵です。一度に 1 人が鍵を持ってトイレを占有できます。終了すると、その人はキューの次の人にキーを渡します (解放します)。
「ミューテックスは通常、複数のスレッドで同時に実行できない再入可能コードのセクションへのアクセスをシリアル化するために使用されます。ミューテックス オブジェクトは、制御されたセクションへの 1 つのスレッドのみを許可し、そのセクションへのアクセスを試みる他のスレッドを強制します。最初のスレッドがそのセクションから出るまで待ちます。"
(mutex は、実際には値 1 を持つセマフォです。)
セマフォ:
無料の同一のトイレの鍵の数です。たとえば、同一の鍵と鍵を持つトイレが 4 つあるとします。セマフォ カウント (キーの数) は、最初は 4 に設定されています (4 つのトイレはすべて空いています)。次に、人が入ってくるとカウント値が減ります。空いているキーが残っていない場合、セマフォ カウントは 0 です。 1 人がトイレを出ると、セマフォが 1 (1 つの無料キー) に増え、順番待ちの次の人に渡されます。
「セマフォは、共有リソースの同時ユーザー数を最大数に制限します。スレッドは、リソースへのアクセスを要求し (セマフォを減らします)、リソースの使用が終了したことを知らせることができます (セマフォを増やします)。」
ソース
セマフォには同期カウンターがあり、ミューテックスは単なるバイナリ (真/偽) です。
セマフォは、使用中のリソースの要素数に応答するための決定的なメカニズムとしてよく使用されます。たとえば、n 個のワーカー スレッドを表すオブジェクトは、使用可能なワーカー スレッドの数をカウントするためにセマフォを使用する場合があります。
真実は、ミューテックスによって同期される INT によってセマフォを表すことができるということです。