ミューテックスを使用する必要がある場合とセマフォを使用する場合


回答:


92

これが私がいつ何を使うべきかを覚えている方法です-

セマフォ: 他のスレッドがウェイクアップするように指示するまで(スレッドが)スリープしたい場合は、セマフォを使用します。セマフォ「ダウン」は1つのスレッド(プロデューサ)で発生し、セマフォ「アップ」(同じセマフォの場合)は別のスレッド(コンシューマ)で発生します。例:プロデューサ-コンシューマの問題で、プロデューサは少なくとも1つのバッファスロットが空になるまでスリープしたい-のみコンシューマスレッドは、バッファスロットが空になったときに通知できます。

ミューテックス: 他のスレッドが同時に実行してはならないコードを(スレッドが)実行したい場合は、ミューテックスを使用します。ミューテックスの「ダウン」は1つのスレッドで発生し、ミューテックスの「アップ」後で同じスレッドで発生する必要があります。例:グローバルリンクリストからノードを削除する場合、ノードを削除している間、別のスレッドがポインタを操作する必要はありません。mutexを取得してノードの削除でビジー状態の場合、別のスレッドが同じmutexを取得しようとすると、mutexを解放するまでスリープ状態になります。

スピンロック: ミューテックスを本当に使用したいが、スレッドのスリープが許可されていない場合は、スピンロックを使用します。例:OSカーネル内の割り込みハンドラーは決してスリープしてはなりません。もしそうなら、システムはフリーズ/クラッシュします。割り込みハンドラーからグローバル共有リンクリストにノードを挿入する必要がある場合は、スピンロックを取得し、ノードを挿入し、スピンロックを解放します。


1
追加する:セマフォとミューテックスは、同期を提供する2つの方法です。セマフォは、シグナリング(プロデューサーおよびコンシューマーの問題のシナリオなど)に関連している可能性があり、ミューテックスは、一度に1つへのアクセスを許可することに関連している可能性があります(共有リソースにアクセスするための複数の要求ですが、一度に許可される要求は1つだけです)。[素敵な記事:geeksforgeeks.org/mutex-vs-semaphore/]
パラッシュ2017

57

ミューテックスは、セマフォにた相互排除オブジェクトですが、一度に1つのロッカーしか許可されず、所有権の制限はセマフォよりも厳しい場合があります。

これは、通常のカウントセマフォ(カウントが1のセマフォ)と同等であると考えることができ、それをロックした同じスレッドによってのみ解放できるという要件(a)

一方、セマフォは任意の数を持ち、その数のロッカーによって同時にロックできます。そして、それを要求したのと同じスレッドによって解放されるという要件がない場合があります(そうでない場合は、割り当てられたメモリのように、現在誰が責任を持っているかを注意深く追跡する必要があります)。

したがって、リソースのインスタンスの数が多い場合(たとえば、3つのテープドライブ)、カウントが3のセマフォを使用できます。これは、どのテープドライブを持っているかを通知しないことに注意してください。特定の数。

また、セマフォを使用すると、単一のロッカーが、テープからテープへのコピーなどのように、リソースの複数のインスタンスをロックする可能性があります。リソースが1つしかない場合(破損したくないメモリの場所など)、mutexの方が適しています。

同等の操作は次のとおりです。

Counting semaphore          Mutual exclusion semaphore
--------------------------  --------------------------
  Claim/decrease (P)                  Lock
  Release/increase (V)                Unlock

余談ですが、セマフォの要求と解放に使用される奇妙な手紙に疑問を抱いたことがある場合は、発明者がオランダ人だったことが原因です。Probeer te verlagenは試行錯誤を繰り返し、verhogenは増加を意味します。


(a) ...または、セマフォとはまったく異なるものと考えることができます。セマフォは、ほとんど常に異なる用途で使用する方が安全です。


さて、私もバイナリセマフォに出くわしました。いつバイナリセマフォを使用する必要があり、いつmutexを使用する必要がありますか?
Karthik Balaguru、2010年

概念的には、バイナリセマフォミューテックスであり、1カウントの通常のセマフォと同等です。効率やリソースの所有権などの概念の実装に違いがある可能性があります(申し立て者以外の誰かによって解放される可能性がありますが、BTWには同意しません-リソースは、それを要求したスレッドによってのみ解放可能であるべきです) )。
paxdiablo 2010年

1
別の潜在的な実装の違いは、再帰的なミューテックスです。リソースは1つしかないため、1つのスレッドで複数回ロックできる場合があります(それを何度も解放する限り)。スレッドが別のインスタンスまたは同じインスタンスを再度要求する必要があるかどうかわからない場合があるため、これは複数インスタンスのリソースではそれほど簡単ではありません。
paxdiablo 2010年

1
特定の問題を解決します。彼らが解決する問題は、ミューテックスをまったく理解していない人であり、決して解決策を軽視すべきではない:-)
paxdiablo

5
ミューテックスは、バイナリセマフォとはまったく異なります。申し訳ありませんが、この定義は間違っています
Peer Stritzinger

49

mutex カウント1のセマフォではないことを理解することは非常に重要です。

これが、バイナリセマフォ(実際にはカウント1のセマフォ)のようなものがある理由です。

MutexとBinary-Semaphoreの違いは、所有権の原則です。

mutexはタスクによって獲得されるため、同じタスクによって解放する必要もあります。これにより、バイナリセマフォに関するいくつかの問題(偶発的な解放、再帰的なデッドロック、優先順位の逆転)を修正できます。

警告:これらの問題が修正されるかどうか、そしてどのように修正されるかはOSの実装次第です。

mutexは同じタスクによって解放される必要があるため、タスクの同期にはあまり適していません。しかし、条件変数と組み合わせると、あらゆる種類のIPCプリミティブを構築するための非常に強力なビルディングブロックが得られます。

したがって、私の推奨事項は、ミューテックスと条件変数(POSIX pthreadsなど)を正しく実装した場合は、これらを使用することです。

セマフォは、解決しようとしている問題に正確に適合する場合にのみ使用し、他のプリミティブを構築しないでください(例:セマフォからのrwロック、ミューテックスおよびこれらの条件変数の使用)

多くの誤解しているミューテックスとセマフォがあります。これまでに見つけた最良の説明は、この3部構成の記事です。

Mutexとセマフォ-パート1:セマフォ

ミューテックス対セマフォ–パート2:ミューテックス

ミューテックス対セマフォ–パート3(最後の部分):相互排除の問題


このサイトへのURLにはファンキーな文字が含まれているため機能しません。現在作業中です
Peer Stritzinger

13

@opaxdiabloの答えは完全に正しいですが、両方の使用シナリオがまったく異なることを指摘しておきます。mutexはコードの一部が同時に実行されるのを防ぐために使用され、セマフォは1つのスレッドが別のスレッドの実行を通知するために使用されます。

/* Task 1 */
pthread_mutex_lock(mutex_thing);
    // Safely use shared resource
pthread_mutex_unlock(mutex_thing);



/* Task 2 */
pthread_mutex_lock(mutex_thing);
   // Safely use shared resource
pthread_mutex_unlock(mutex_thing); // unlock mutex

セマフォのシナリオは異なります。

/* Task 1 - Producer */
sema_post(&sem);   // Send the signal

/* Task 2 - Consumer */
sema_wait(&sem);   // Wait for signal

詳細については、http://www.netrino.com/node/202を参照してください


2
あなたが正しい。カウントが1のセマフォを使用している場合でも、ミューテックスを使用している場合よりも、何をしているのかを示唆しています。
Omnifarious

私はそれに同意するかどうかはわかりませんが、私はあなたに反対票を投じるほど激しい意見に同意しません:-)セマフォの使用パターンはスレッドに通知することですが、別のスレッドが待機しているときにミューテックスが行うことは正確ですその上で、セマフォがまさにないで何のスレッドがないときsema_wait:-)私の意見では、彼らがしているの両方をリソースについて、その他のスレッドに渡さ通知は、(非常に重要な、性能面)の副作用であります保護。
paxdiablo 2010年

You say that the usage pattern of semaphores is to notify threadsスレッドの通知に関する1つのポイント。あなたは呼び出すことができますsem_post(シグナルハンドラから安全pubs.opengroup.org/onlinepubs/009695399/functions/...)それはコールにお奨めされていないpthread_mutex_lockと、pthread_mutex_unlockシグナルハンドラ(からmanpages.ubuntu.com/manpages/lucid/man3/...

@paxdiablo:このミューテックスバイナリセマフォには、参照カウントの維持に大きな違いがあります。ミューテックス、または条件付きミューテックスは、カウントが維持されるために使用されるように、ロックに関連するカウントを維持しないと言えます。したがって、sem_waitとsem_postはカウントを維持しています。
Prak 2013

9

「トイレの例」を参照してください-http : //pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm

ミューテックス:

トイレの鍵です。一度に一人が鍵を手に入れることができます-トイレを占有します-。終了すると、その人はキュー内の次の人に鍵を渡します(解放します)。

公式には、「ミューテックスは通常、複数のスレッドで同時に実行できない再入可能コードのセクションへのアクセスをシリアル化するために使用されます。ミューテックスオブジェクトは、制御されたセクションに1つのスレッドのみを許可し、他のスレッドにアクセスを試行させます。そのセクションから、最初のスレッドが終了するまで待機します。」参照:Symbian開発者ライブラリ

(ミューテックスは実際には値1のセマフォです。)

セマフォ:

無料の同じトイレの鍵の数です。例として、鍵と鍵が同じトイレが4つあるとします。セマフォの数-キーの数-は最初は4に設定され(4つのトイレはすべて無料)、人が入るにつれてカウント値は減少します。空きキーが残っていないため、セマフォカウントは0です。1人がトイレを離れると、セマフォが1(1つのフリーキー)に増加し、キューの次の人に渡されます。

公式に:「セマフォは共有リソースの同時ユーザー数を最大数に制限します。スレッドはリソースへのアクセスを要求でき(セマフォを減らします)、リソースの使用が終了したことを通知できます(セマフォを増やします)。 」参照:Symbian開発者ライブラリ


7

気まぐれに聞こえないようにしようとしていますが、自分自身を助けることはできません。

あなたの質問は、ミューテックスとセマフォの違いは何ですか?より正確に言えば、「ミューテックスとセマフォの関係は何ですか?」

(私はその質問を追加しましたが、熱心なモデレーターが違いと関係の違いを理解せずに重複として閉じると確信しています。)

オブジェクトの用語では、次のことがわかります。

観察.1セマフォはミューテックスを含む

観察.2ミューテックスはセマフォではなく、セマフォはミューテックスではありません。

バイナリセマフォと呼ばれる、それらがミューテックスであるかのように動作するいくつかのセマフォがありますが、それらはミューテックスではありません。

シグナリング(posixはその名前にcondition_variableを使用)と呼ばれる特別な要素があり、ミューテックスからセマフォを作成するために必要です。通知元と考えてください。2つ以上のスレッドが同じnotification-sourceにサブスクライブしている場合、それらのメッセージをONEまたはALLに送信してウェイクアップすることが可能です。

mutexによって保護されているセマフォに関連付けられた1つ以上のカウンターが存在する可能性があります。セマフォの最も単純なシナリオは、0または1のいずれかになる単一のカウンターです。

これは、モンスーンの雨のように混乱が降り注ぐ場所です。

カウンターが0または1のセマフォはミューテックスではありません。

Mutexには2つの状態(0,1)と1つの所有権(タスク)があります。セマフォには、ミューテックス、いくつかのカウンタ、および条件変数があります。

今、あなたの想像力を使用してください、そしてカウンターの使用法といつ合図するかについてのあらゆる組み合わせは、一種のセマフォを作ることができます。

  1. 値0または1の単一カウンターと、値が1になり、信号を待っている人の1人のロックを解除する==バイナリセマフォ

  2. 値0からNまでの単一のカウンター。値がN未満になるとシグナルを送信し、値がNの場合はロック/待機==カウントセマフォ

  3. 値0からNまでの単一のカウンター。値がNになったときに信号を送信し、値がN未満のときにロック/待機する==バリアセマフォ(呼び出していない場合は、呼び出します)。

さて、あなたの質問ですが、いつ何を使うべきか。(または、mutexを使用する場合と、バイナリセマフォを使用しない場合は、質問version.3を修正します。非バイナリセマフォとの比較がないためです。)バイナリで提供されていないカスタマイズされた動作が必要な場合は、1。を使用します。スピンロック、ファストロック、再帰的ロックなどのセマフォ。通常、属性を指定してミューテックスをカスタマイズできますが、セマフォのカスタマイズは、新しいセマフォを作成することに他なりません。2.軽量またはより高速なプリミティブが必要

必要なものが正確に提供される場合は、セマフォを使用します。

バイナリセマフォの実装によって何が提供されているのか理解できない場合は、IMHOでmutexを使用してください。

そして最後に、SOだけに頼るのではなく、本を読んでください。


5

問題は、ミューテックスとバイナリセマフォの違いだと思います。

Mutex =所有権ロックメカニズムであり、ロックを取得したスレッドのみがロックを解放できます。

バイナリセマフォ=シグナルメカニズムであり、必要に応じて他の優先度の高いスレッドがシグナルを送信してロックを取得できます。


5

ミューテックスは、共有リソースを保護することです。
セマフォはスレッドをディスパッチすることです。

ミューテックス:
販売するチケットがあるとします。多くの人が同時にチケットを購入する場合をシミュレーションできます。各人がチケットを購入するためのスレッドです。チケットは共有リソースであるため、明らかにミューテックスを使用してチケットを保護する必要があります。


セマフォ:
以下のように計算する必要があると想像してください:

c = a + b;

また、geta()計算する関数、計算aする関数getb()、計算bを行う関数getc()も必要ですc = a + b

もちろん、我々は行うことができないc = a + b場合を除きgeta()getb()仕上げられています。
3つの関数が3つのスレッドの場合、3つのスレッドをディスパッチする必要があります。

int a, b, c;
void geta()
{
    a = calculatea();
    semaphore_increase();
}

void getb()
{
    b = calculateb();
    semaphore_increase();
}

void getc()
{
    semaphore_decrease();
    semaphore_decrease();
    c = a + b;
}

t1 = thread_create(geta);
t2 = thread_create(getb);
t3 = thread_create(getc);
thread_join(t3);

セマフォの助けを借りて、上記のコードは、それが確認することができt3、その仕事は、それまではしないだろうt1し、t2彼らの仕事を行っています。

つまり、セマフォはスレッドを論理的な順序で実行することですが、ミューテックスは共有リソースを保護することです。
したがって、ミューテックスは初期値が1の特別なセマフォであると常に言う人がいても、同じではありません。このように言うこともできますが、異なる場合に使用されることに注意してください。それが可能であっても、一方を他方に置き換えないでください。


チケットを売るのは良い例です。セマフォの例は(とにかく私にとって)少し不明瞭です。
prayagupd 2017

1
@prayagupdセマフォの例は、ある順序でスレッドを作成することですが、チケットの販売には順序は必要ありません。3人の場合:a、b、c。彼らがチケットを購入するときは、チケットを購入する順序をまったく気にしません。私たちはこのような計算を行う場合は、:x = getx(); y = gety(); z = x + y;私たちが行うことはできませんので、いくつかの理由について、我々は3つのことを行うために3つのスレッドを使用して、今のスレッドの順序は非常に重要であるx + y場合を除きgetxそしてgety終了しました。つまり、セマフォはマルチスレッドの実行順序を気にするときに使用されます。
Yvesが

つかまえた。それは障壁に似ているように聞こえます。私は、スレッドまでその待ち時間を言うことができるxy、その計算を完了していますz = x + y。私はjavaが持っていることを知っていCyclicBarrierます。また、mapreduceセマフォのユースケースも言えるかどうかはわかりません。reduceすべてmapのsが完了するまでは、そうすることができないためです。
prayagupd 2017

@prayagupdはい。そうとも言える。
Yvesは

2

上記のすべての答えは良質ですが、これは覚えておくためのものです。ミューテックスの名前は相互排他に由来しているため、ミューテックスロックは、相互に排他的であるとして相互に排他的であると相互に考えます。それを所有していて、私がそれを解放した後で初めてそれを手に入れることができます。一方、そのようなケースはセマフォには存在しません。これは信号機のようなものです(セマフォという言葉も意味します)。


1

指摘したように、カウントが1のセマフォは、ミューテックスと同じ「バイナリ」セマフォと同じです。

私が使用したものより数が多いセマフォを見た主なものは、特定の固定サイズのキューがあるプロデューサー/コンシューマーの状況です。

その場合、セマフォは2つあります。最初のセマフォはキューの項目数に最初に設定され、2番目のセマフォは0に設定されます。プロデューサは最初のセマフォに対してP操作を実行し、キューに追加します。2番目にV演算を実行します。コンシューマは2番目のセマフォでP操作を実行し、キューから削除してから、最初のセマフォでV操作を実行します。

このようにして、プロデューサーはキューがいっぱいになるとブロックされ、コンシューマーはキューが空になるとブロックされます。


1

ミューテックスはセマフォの特殊なケースです。セマフォにより、いくつかのスレッドがクリティカルセクションに入ることができます。セマフォを作成するときに、クリティカルセクションでスレッドを許可する方法を定義します。もちろん、コードはこの重要なセクションへのいくつかのアクセスを処理できなければなりません。


-1

バイナリセマフォとミューテックスは異なります。OSの観点からは、バイナリセマフォとカウントセマフォは同じ方法で実装され、バイナリセマフォは値0または1を持つことができます。

Mutex- >コードの重要なセクションの相互排他の唯一の目的にのみ使用できます。

セマフォ ->さまざまな問題を解決するために使用できます。バイナリセマフォはシグナリングに使用でき、相互排除の問題も解決します。0に初期化するとシグナリングの問題が解決され、1に初期化すると相互排除の問題が解決されます。

リソースの数が多く、同期が必要な場合は、セマフォのカウントを使用できます。

私のブログでは、これらのトピックについて詳しく説明しました。

https://designpatterns-oo-cplusplus.blogspot.com/2015/07/synchronization-primitives-mutex-and.html

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.