いつmutexを使用し、いつセマフォを使用する必要がありますか?
以下は、いつ何を使用するかを覚えている方法です-
セマフォ:他のスレッドがウェイクアップするように指示するまで(スレッド)スリープしたい場合は、セマフォを使用します。セマフォ「ダウン」は1つのスレッド(プロデューサ)で発生し、セマフォ「アップ」(同じセマフォ)は別のスレッド(コンシューマ)で発生します。コンシューマスレッドは、バッファスロットが空になったことを知ることができます。
Mutex:同時に他のスレッドによって実行されるべきではないコードを(スレッド)実行したい場合、ミューテックスを使用します。ミューテックス「ダウン」は1つのスレッドで発生し、ミューテックス「アップ」mustは後で同じスレッドで発生します。例:グローバルリンクリストからノードを削除する場合、ノードを削除している間、別のスレッドがポインターでいじくり回したくありません。ミューテックスを取得し、ノードの削除でビジーな場合、別のスレッドが同じミューテックスを取得しようとすると、ミューテックスを解放するまでスリープ状態になります。
Spinlock:ミューテックスを本当に使用したいが、スレッドがスリープできない場合にスピンロックを使用します。例:OSカーネル内の割り込みハンドラーは決してスリープしてはいけません。そうなると、システムがフリーズ/クラッシュします。割り込みハンドラーからグローバル共有リンクリストにノードを挿入する必要がある場合は、スピンロック-ノードの挿入-スピンロックの解放を取得します。
ミューテックスは、セマフォに対する相互排他オブジェクトsimilarですが、一度に1つのロッカーのみを許可し、所有権の制限はセマフォよりも厳しい場合があります。
通常のカウントセマフォ(カウント1)と同等であると考えることができ、それをロックした同じスレッドによってのみ解放できるという要件(a)。
一方、セマフォには任意のカウントがあり、その数のロッカーによって同時にロックできます。そして、それを要求したのと同じスレッドによってリリースされる必要はないかもしれません(ただし、そうでない場合、割り当てられたメモリのように、現在誰が責任を持っているかを注意深く追跡する必要があります)。
したがって、リソースのインスタンス(たとえば3つのテープドライブ)が多数ある場合は、カウント3のセマフォを使用できます。これは、所有しているテープドライブがどれであるかはわかりません。特定の数。
また、セマフォを使用すると、単一のロッカーで、テープからテープへのコピーなど、リソースの複数のインスタンスをロックできます。 1つのリソース(破損したくないメモリの場所など)がある場合は、ミューテックスの方が適しています。
同等の操作は次のとおりです。
Counting semaphore Mutual exclusion semaphore
-------------------------- --------------------------
Claim/decrease (P) Lock
Release/increase (V) Unlock
脇:セマフォの主張と解放に使用される奇妙な文字に疑問を抱いたことがある場合、それは発明者がオランダ人だったからです。プローバーテベルラゲンは、バーゲンが増加することを意味する一方で、減少を試みることを意味します。
(a) ...または、セマフォとはまったく異なる何かと考えることができます。セマフォは、ほぼ常に異なる用途を考えればより安全かもしれません。
ミューテックスはカウント1のセマフォではないことを理解することが非常に重要です!
これが、バイナリセマフォ(実際にはカウント1のセマフォ)のようなものがある理由です。
MutexとBinary-Semaphoreの違いは、所有権の原則です。
ミューテックスはタスクによって取得されるため、同じタスクによって解放される必要があります。これにより、バイナリセマフォに関するいくつかの問題(非公開リリース、再帰的デッドロック、優先度反転)を修正できます。
警告:これらの問題を修正する方法とその方法がOSの実装次第であれば、「可能にする」と書きました。
ミューテックスは同じタスクによって解放される必要があるため、タスクの同期にはあまり適していません。ただし、条件変数と組み合わせると、あらゆる種類のipcプリミティブを構築するための非常に強力な構築ブロックが得られます。
ですから、私の推奨事項は次のとおりです。きれいに実装されたmutexと条件変数(POSIX pthreadの場合など)を使用する場合。
セマフォは、解決しようとしている問題に正確に適合する場合にのみ使用し、他のプリミティブを構築しようとしないでください(たとえば、セマフォからrw-locks、これらにミューテックスと条件変数を使用)
ミューテックスとセマフォには多くの誤解があります。これまでに見つけた最良の説明は、この3部構成の記事にあります。
@opaxdiabloの答えは完全に正しいですが、両方の使用シナリオがまったく異なることを指摘したいと思います。ミューテックスは、コードの一部が同時に実行されるのを防ぐために使用され、セマフォは、あるスレッドが別のスレッドに実行を通知するために使用されます。
/* 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_lock(mutex_thing);
セマフォのシナリオは異なります。
/* Task 1 - Producer */
sema_post(&sem); // Send the signal
/* Task 2 - Consumer */
sema_wait(&sem); // Wait for signal
詳細については、 http://www.netrino.com/node/202 を参照してください
「トイレの例」を参照してください- http://pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm :
Mutex:
トイレの鍵です。その時、一人が鍵を手に入れることができます-トイレを占有します。終了すると、その人はキュー内の次の人にキーを渡します(解放します)。
公式:「Mutexeは通常、複数のスレッドで同時に実行できないリエントラントコードのセクションへのアクセスをシリアル化するために使用されます。mutexオブジェクトは、1つのスレッドのみを制御セクションに入れ、他のスレッドがそのセクションから最初のスレッドが終了するまで待機するセクション。」参照:Symbian開発者ライブラリ
(ミューテックスは実際には値1のセマフォです。)
セマフォ:
無料の同一トイレキーの数です。たとえば、同じ鍵と鍵を備えた4つのトイレがあるとします。セマフォカウント-キーのカウント-は開始時に4に設定され(4つのトイレはすべて無料)、カウント値は人々が入ってくるとデクリメントされます。空きキーが残っていない場合、セマフォカウントは0です。 1人がトイレを離れ、セマフォが1(無料のキー1つ)に増え、キュー内の次の人に与えられます。
公式:「セマフォは、共有リソースの同時ユーザー数を最大数に制限します。スレッドはリソースへのアクセスを要求(セマフォをデクリメント)でき、リソースの使用を終了したことを通知(セマフォをインクリメント)できます。 」参照:Symbian開発者ライブラリ
こっけいに聞こえないようにしようとするが、自分自身を助けることはできません。
あなたの質問は、ミューテックスとセマフォの違いは何ですか?さらに正確に言うと、「ミューテックスとセマフォとの関係は何ですか?」
(私はその質問を追加したでしょうが、違いと関係の違いを理解することなく、熱心なモデレーターが重複としてそれを閉じると確信しています。)
オブジェクトの用語では、次のことがわかります。
observation.1セマフォにミューテックスが含まれる
observation.2ミューテックスはセマフォではなく、セマフォはミューテックスではありません。
バイナリセマフォと呼ばれるミューテックスであるかのように動作するセマフォがいくつかありますが、ミューテックスではありません。
ミューテックスからセマフォを作成するために必要な、Signaling(posixはその名前にcondition_variableを使用)と呼ばれる特別な成分があります。通知ソースと考えてください。 2つ以上のスレッドが同じ通知ソースにサブスクライブしている場合、それらを1つまたはすべてに送信して、ウェイクアップすることができます。
相互排他ロックによって保護されているセマフォに関連付けられた1つ以上のカウンタが存在する可能性があります。セマフォの最も単純なシナリオでは、0または1のいずれかになる単一のカウンターがあります。
モンスーンの雨のように混乱が入る場所です。
0または1の可能性があるカウンタを持つセマフォはミューテックスではありません。
Mutexには2つの状態(0,1)と1つの所有権(タスク)があります。セマフォには、ミューテックス、いくつかのカウンター、条件変数があります。
今、あなたの想像力を使い、カウンターの使用法とシグナルを送るタイミングのあらゆる組み合わせで、1種類のセマフォを作ることができます。
値が0または1で、値が1になったときに信号を送信し、信号を待っている男の1人をロック解除する単一のカウンター==バイナリセマフォ
値が0〜Nで、値がN未満になった場合にシグナルを送信し、値がNの場合にロック/待機する単一のカウンター==カウントセマフォ
値が0からNで、値がNになったときにシグナルを送信し、値がNより小さい場合にロック/待機する単一のカウンター==バリアセマフォ(呼び出していない場合は、そうする必要があります)
さてあなたの質問に、いつ何を使うべきか。 (または、非バイナリセマフォとの比較がないため、どちらの場合はmutexを使用し、バイナリセマフォを使用するかは質問バージョン3を修正してください。)1.バイナリで提供されないカスタマイズされた動作が必要な場合セマフォ(スピンロック、高速ロック、再帰ロックなど)。通常、属性を使用してミューテックスをカスタマイズできますが、セマフォのカスタマイズは新しいセマフォの作成に他なりません。 2.軽量のOR高速プリミティブが必要な場合
必要なものが正確に提供されている場合は、セマフォを使用します。
バイナリセマフォの実装によって提供されるものがわからない場合は、次にIMHOを使用して、mutexを使用します。
最後に、SOだけに頼るのではなく、本を読んでください。
質問は、ミューテックスとバイナリセマフォの違いだと思います。
ミューテックス=これは所有権ロックメカニズムであり、ロックを取得したスレッドのみがロックを解除できます。
バイナリセマフォ=これはシグナルメカニズムであり、必要に応じて他の優先度の高いスレッドがシグナルを送信してロックを取得できます。
ミューテックスは共有リソースを保護することです。
セマフォはスレッドをディスパッチします。
ミューテックス:
販売するチケットがあることを想像してください。多くの人が同時にチケットを購入する場合をシミュレートできます。各人はチケットを購入するスレッドです。明らかに、mutexは共有リソースであるため、チケットを保護するためにmutexを使用する必要があります。
セマフォ:
次のように計算する必要があると想像してください。
c = a + b;
また、a
を計算する関数geta()
、b
を計算する関数getb()
、およびc = a + b
を計算する関数getc()
が必要です。
明らかに、geta()
とgetb()
が終了しない限り、c = a + b
は実行できません。
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
がそのジョブを実行しないことを確認できます。
Wordでは、セマフォはスレッドを論理的な順序で実行することであり、ミューテックスは共有リソースを保護することです。
したがって、mutexは初期値1の特別なセマフォであるといつも言っている人でも、同じことではありません。たとえそれを行うことができたとしても、一方を他方に置き換えないでください。
上記の答えはすべて良質ですが、これは覚えておくだけです。名前Mutexは、Mutually Exclusiveに由来します。したがって、ミューテックスロックを2つの間の相互排他と見なすように動機付けられ、一度に1つだけのように、所有している場合は、解放した後にのみそれを保持できます。一方、そのようなケースは存在しません- セマフォは、信号機のようなものです(ワードセマフォも意味します)。
指摘したように、カウントが1のセマフォは、ミューテックスと同じものである「バイナリ」セマフォと同じものです。
私が使用したものよりも大きいカウントのセマフォを見た主なものは、特定の固定サイズのキューがあるプロデューサー/コンシューマーの状況です。
2つのセマフォがあります。最初のセマフォはキュー内のアイテム数に初期設定され、2番目のセマフォは0に設定されます。プロデューサは最初のセマフォでP操作を実行し、キューに追加します。 2番目のV操作を実行します。コンシューマは2番目のセマフォでP操作を実行し、キューから削除してから、最初のセマフォでV操作を実行します。
このようにして、キューがいっぱいになるとプロデューサーがブロックされ、キューが空になるとコンシューマーがブロックされます。
ミューテックスはセマフォの特殊なケースです。セマフォを使用すると、いくつかのスレッドをクリティカルセクションに入れることができます。セマフォを作成するとき、クリティカルセクションでスレッドを許可する方法を定義します。もちろん、コードはこのクリティカルセクションへの複数のアクセスを処理できる必要があります。