Java?主な違いは何ですか?
セマフォはカウントできますが、ミューテックスは1までしかカウントできません。
クライアント接続を受け入れるスレッドが実行されているとします。このスレッドは10個のクライアントを同時に処理できます。その後、新しいクライアントはそれぞれ10に達するまでセマフォを設定します。セマフォに10個のフラグがある場合、スレッドは新しい接続を受け入れません。
ミューテックスは通常、物を守るために使用されます。 10人のクライアントがシステムの複数の部分にアクセスできるとします。その後、ミューテックスを使用してシステムの一部を保護することができるため、1つのクライアントがそのサブシステムに接続されている場合、他のユーザーはアクセスできません。この目的にもセマフォを使用できます。ミューテックスは "Mutual Exclusion Semaphore" です。
残念ながら、誰もがセマフォとミューテックスの最も重要な違いを見逃しています。 「所有権」の概念。
セマフォには所有権の概念がありません。これは、どのスレッドもセマフォを解放できることを意味します(これにより多くの問題が発生する可能性がありますが、「死の検出」には役立ちます)。一方、ミューテックスには所有権の概念があります(つまり、取得したミューテックスのみをリリースできます)。
所有権は、並行システムの安全なプログラミングにとって非常に重要です。セマフォよりもミューテックスを優先して使用することを常にお勧めします(ただし、パフォーマンスへの影響があります)。
ミューテックスは、優先度の継承(優先度の逆転の問題に役立つ)と再帰(デッドロックの1つのタイプを排除する)もサポートします。
「バイナリ」セマフォと「カウント/一般」セマフォがあることも指摘しておく必要があります。 Javaのセマフォはカウントセマフォであるため、1より大きい値で初期化することができます(一方、指摘したように、mutexは1の概念的なカウントしかできません)。これの有用性は他の投稿で指摘されています。
要約すると、管理するリソースが複数ない限り、セマフォよりもミューテックスを常にお勧めします。
ミューテックスは基本的に相互排除です。一度に1つのスレッドのみがリソースを取得できます。 1つのスレッドがリソースを取得すると、リソースを所有しているスレッドが解放されるまで、他のスレッドはリソースを取得できません。リソースの取得を待機しているすべてのスレッドがブロックされます。
セマフォは、実行中のスレッドの数を制御するために使用されます。リソースの固定セットがあります。リソースカウントは、スレッドが同じものを所有するたびに減少します。セマフォカウントが0に達すると、他のスレッドはリソースを取得できなくなります。スレッドは、リソースを所有する他のスレッドが解放されるまでブロックされます。
要するに、主な違いは一度にリソースを取得できるスレッドの数?
相互排他ロックはリソースへのシリアルアクセスに使用され、セマフォはリソースへのアクセスを設定された数まで制限します。ミューテックスは、アクセスカウントが1のセマフォと考えることができます。セマフォカウントをどのように設定しても、スレッドはリソースがブロックされる前にリソースにアクセスできます。
セマフォはカウント同期メカニズムであり、ミューテックスはそうではありません。
ミューテックスは、バイナリセマフォとしてよく知られています。セマフォはゼロ以外のカウントで作成できますが、ミューテックスは概念的には上限カウントが1のセマフォです。
この質問には関連する回答と公式のJavaガイダンスへのリンクがあります: Javaにミューテックスはありますか?
比類のない、技術的にセマフォとそれが意味をなさないミューテックスの間に違いがないことを比較します。ミューテックスは、アプリケーションロジックの名前のような重要な名前です。つまり、セマフォを「1」に初期化します。これは、相互排除を保証するためにリソースまたは保護変数を保護するために一般的に使用されます。
セマフォ :
カウントセマフォ。概念的には、セマフォは一連の許可を保持します。各
acquire()
は、許可が使用可能になるまで必要に応じてブロックし、それを取得します。各release()
は許可を追加し、潜在的にブロッキング取得者を解放します。ただし、実際の許可オブジェクトは使用されません。セマフォは使用可能な数のカウントを保持し、それに応じて動作します。
セマフォは、いくつかの(物理または論理)リソースにアクセスできるスレッド数を制限するためによく使用されます
Javaには、組み込みのMutex APIはありません。ただし、バイナリセマフォとして実装できます。
1に初期化され、使用可能な許可が1つだけになるように使用されるセマフォは、相互排他ロックとして機能します。これは、一般にバイナリセマフォとして知られています。これは、許可が1つ、許可が0の2つの状態しかないためです。
この方法で使用すると、バイナリセマフォにプロパティがあります(多くのロック実装とは異なり)「ロック」は所有者以外のスレッドによって解放できます(セマフォには所有権の概念がないため) 。これは、デッドロックリカバリなどの特殊なコンテキストで役立ちます。
キーの違い セマフォとミューテックス:
セマフォは、許可によりリソースにアクセスするスレッドの数を制限します。 Mutexでは、リソースにアクセスできるスレッドは1つだけです。
セマフォを所有するスレッドはありません。スレッドは、acquire()
およびrelease()
メソッドを呼び出すことにより、許可の数を更新できます。ミューテックスは、ロックを保持しているスレッドによってのみロック解除する必要があります。
ミューテックスが条件変数で使用される場合、暗黙のブラケットがあります。明確ですプログラムのどの部分が保護されていますか d。これは、必ずしもセマフォの場合ではありません。セマフォは、並行プログラミングに進むと呼ばれる場合があります。強力ですが、構造化されていない不確定な方法で使いやすいです。
ミューテックスはバイナリセマフォです。先着順の原則が満たされるように、1で初期化する必要があります。これにより、各ミューテックスの他の特別なプロパティが得られます。downを実行した人は、upを実行した人でなければなりません。エルゴは、いくつかのリソースに対して相互排除を取得しました。
ミューテックスは一般的なセマフォの特殊なケースであることがわかります。
同期のオブジェクトセマフォは、古典的な信号機を実装しています。信号機は、カウンターが共有するリソースへのアクセスを制御します。カウンターがゼロより大きい場合、アクセスが許可されます。ゼロの場合、アクセスは拒否されます。カウンターは、共有リソースへのアクセスを許可するアクセス許可をカウントします。次に、リソースにアクセスするには、スレッドは信号機から許可を受け取る必要があります。一般に、信号機を使用するには、共有リソースにアクセスするスレッドが許可を取得しようとします。信号機のカウントがゼロより大きい場合、スレッドは許可を取得し、信号機のカウントは減らされます。それ以外の場合、スレッドは許可を取得できるまでロックされます。スレッドが共有リソースにアクセスする必要がなくなると、アクセス権が解放されるため、信号機の数が増えます。許可を待っている別のスレッドがある場合、その時点で許可を取得します。 Javaのセマフォクラスは、このメカニズムを実装します。
セマフォには2つのビルダーがあります。
Semaphore(int num)
Semaphore(int num, boolean come)
numは、許可の初期カウントを指定します。次に、numは、特定の時間に共有リソースにアクセスできるスレッドの数を指定します。 numが1の場合、一度に1つのスレッドでリソースにアクセスできます。 comeをtrueに設定することで、待機しているスレッドに要求した順序で許可が与えられることを保証できます。