バイナリセマフォとミューテックスの間に違いはありますか、それとも本質的に同じですか?
バイナリセマフォとミューテックスの間に違いはありますか、それとも本質的に同じですか?
回答:
それらは同じものではありません。それらはさまざまな目的で使用されます!
どちらのタイプのセマフォもフル/空の状態であり、同じAPIを使用しますが、使用方法は大きく異なります。
相互排除セマフォ
相互排除セマフォは、共有リソース(データ構造、ファイルなど)を保護するために使用されます。
Mutexセマフォは、それを受け取るタスクによって「所有」されます。タスクBが現在タスクAが保持しているミューテックスをsemGiveしようとすると、タスクBの呼び出しはエラーを返し、失敗します。
mutexは常に次のシーケンスを使用します。
-SemTake -重要なセクション -SemGive
以下に簡単な例を示します。
スレッドAスレッドB ミューテックスを取る データにアクセスする ...ミューテックス<==をブロックします ... Mutexにアクセスデータを提供<==ブロック解除 ... ミューテックスを与える
バイナリセマフォ
バイナリセマフォは、まったく異なる質問に対応します。
Task A Task B
... Take BinSemaphore <== wait for something
Do Something Noteworthy
Give BinSemaphore do something <== unblocks
バイナリセマフォでは、Bがセマフォを取得し、Aがセマフォを取得しても問題ないことに注意してください。
この場合も、バイナリセマフォはリソースをアクセスから保護していません。セマフォを与えて取るという行為は、基本的に切り離されています。
通常、同じバイナリセマフォに対してギブアンドテイクを行うことは、同じタスクにはほとんど意味がありません。
そのため、セマフォは、プロデューサー/コンシューマーなどのいくつかの同期問題に適しています。
Windowsでは、バイナリセマフォはミューテックスよりもイベントオブジェクトに似ています。
Mutex can be released only by thread that had acquired it
-単純なpthread_mutexベースのプログラムで試したところ、メインスレッドでロックされているミューテックスをスレッドがロック解除できる
トイレの例は楽しいアナロジーです:
ミューテックス:
トイレの鍵です。一度に一人の人が鍵を手に入れることができます-トイレを占有します-。終了すると、その人はキュー内の次の人に鍵を渡します(解放します)。
公式には、「Mutexeは通常、複数のスレッドで同時に実行できない再入可能コードのセクションへのアクセスをシリアル化するために使用されます。ミューテックスオブジェクトは、制御されたセクションに1つのスレッドのみを許可し、他のスレッドにアクセスを試行させます。そのセクションから、最初のスレッドが終了するまで待機します。」参照:Symbian開発者ライブラリ
(ミューテックスは実際には値1のセマフォです。)
セマフォ:
無料の同じトイレの鍵の数です。例として、鍵と鍵が同じトイレが4つあるとします。セマフォの数-キーの数-は最初は4に設定され(4つのトイレはすべて無料)、人が入るにつれてカウント値は減少します。すべてのトイレがいっぱいの場合、つまり 空きキーが残っていないため、セマフォカウントは0です。1人がトイレを離れると、セマフォが1(1つのフリーキー)に増加し、キュー内の次の人に渡されます。
公式に:「セマフォは共有リソースの同時ユーザー数を最大数に制限します。スレッドはリソースへのアクセスを要求でき(セマフォを減らします)、リソースの使用が終了したことを通知できます(セマフォを増やします)。 」参照:Symbian開発者ライブラリ
トピックに関する素晴らしい記事:
パート2から:
ミューテックスはバイナリセマフォの原則に似ていますが、所有権の原則という大きな違いがあります。所有権とは、タスクがmutexをロック(取得)すると、それだけがロック解除(解放)できるという単純な概念です。タスクがロックしていない(つまり所有していない)ミューテックスをロック解除しようとすると、エラー条件が発生し、最も重要なことには、ミューテックスはロック解除されません。相互排除オブジェクトが所有権を持たない場合、それが何と呼ばれるかに関係なく、それはミューテックスではありません。
上記の答えはどれも混乱を解消しないので、ここに私の混乱を解消したものがあります。
厳密に言うと、mutexはリソースへのアクセスを同期するために使用されるロックメカニズムです。mutexを取得できるのは、1つのタスク(OS抽象化に基づくスレッドまたはプロセスにすることができます)のみです。つまり、mutexに関連付けられた所有権が存在し、所有者だけがロック(mutex)を解放できます。
セマフォはシグナリングメカニズムです(「完了しました。続行できます」のような信号です)。たとえば、携帯電話で曲を聴いているとき(それを1つのタスクと想定)、友人があなたに電話をかけると同時に、割り込みがトリガーされ、割り込みサービスルーチン(ISR)がコール処理タスクにウェイクアップするようシグナルを送ります。 。
同期のセマンティクスは大きく異なります。
そのような一つのタスクからタスクおよびトラフィックとしてセマフォに渡されるトークンとしてミューテックスを見ることができるように赤色光(それは信号が進行することができることを誰かに)。
理論的なレベルでは、それらは意味的に違いはありません。セマフォを使用してミューテックスを実装することも、その逆も可能です(例についてはこちらを参照)。実際には、実装は異なり、わずかに異なるサービスを提供します。
(それらを取り巻くシステムサービスの点で)実際的な違いは、ミューテックスの実装がより軽量な同期メカニズムであることを目的としていることです。oracle-speakでは、ミューテックスはラッチと呼ばれ、セマフォは待機と呼ばれます。
最下位レベルでは、ある種のアトミックテストと設定メカニズムを使用します。これは、メモリ位置の現在の値を読み取り、何らかの条件を計算し、その位置で、割り込みできない単一の命令で値を書き込みます。つまり、ミューテックスを取得して、他の誰かがあなたの前に持っていたかどうかをテストすることができます。
典型的なミューテックスの実装には、テストと設定の命令を実行し、他に何かがミューテックスを設定したかどうかを評価するプロセスまたはスレッドがあります。ここでの重要な点は、スケジューラとの相互作用がないため、誰がロックを設定したのかわかりません(気にしない)。次に、タイムスライスをあきらめて、タスクが再スケジュールされたときに再試行するか、スピンロックを実行します。スピンロックは次のようなアルゴリズムです。
Count down from 5000:
i. Execute the test-and-set instruction
ii. If the mutex is clear, we have acquired it in the previous instruction
so we can exit the loop
iii. When we get to zero, give up our time slice.
保護されたコード(クリティカルセクションと呼ばれます)の実行が終了したら、mutex値をゼロまたは「クリア」を意味する値に設定します。複数のタスクがミューテックスを取得しようとしている場合、ミューテックスが解放された後にたまたまスケジュールされている次のタスクがリソースにアクセスします。通常、ミューテックスを使用して、同期されたリソースを制御します。このリソースでは、通常、共有データ構造を更新するために、非常に短い期間だけ排他アクセスが必要です。
セマフォは、(通常はミューテックスを使用して)同期されたデータ構造であり、カウントと、ミューテックスライブラリよりも少し深くスケジューラとやり取りするいくつかのシステムコールラッパーを持っています。セマフォはインクリメントおよびデクリメントされ、他の準備ができるまでタスクをブロックするために使用されます。この簡単な例については、プロデューサー/コンシューマーの問題を参照してください。セマフォはある値に初期化されます。バイナリセマフォは、セマフォが1に初期化される特殊なケースです。セマフォにポストすると、待機中のプロセスが起動します。
基本的なセマフォアルゴリズムは次のようになります。
(somewhere in the program startup)
Initialise the semaphore to its start-up value.
Acquiring a semaphore
i. (synchronised) Attempt to decrement the semaphore value
ii. If the value would be less than zero, put the task on the tail of the list of tasks waiting on the semaphore and give up the time slice.
Posting a semaphore
i. (synchronised) Increment the semaphore value
ii. If the value is greater or equal to the amount requested in the post at the front of the queue, take that task off the queue and make it runnable.
iii. Repeat (ii) for all tasks until the posted value is exhausted or there are no more tasks waiting.
バイナリセマフォの場合、2つのセマフォの主な実用的な違いは、実際のデータ構造を取り巻くシステムサービスの性質です。
編集:エヴァンが正しく指摘したように、スピンロックはシングルプロセッサマシンの速度を低下させます。シングルプロセッサでは、ミューテックスを保持するプロセスが別のタスクの実行中にmutexをリセットすることはないため、マルチプロセッサボックスでのみスピンロックを使用します。スピンロックは、マルチプロセッサアーキテクチャでのみ役立ちます。
futex
システムコールは、低レイテンシのユーザースペースミューテックス/セマフォの実装を支援するために存在します。en.wikipedia.org / wiki / Futex)競合なしの高速パスで、またはリソースがすぐに利用可能になった場合、オーバーヘッドが発生することはありませんシステムコール。しかし、数マイクロ秒以上ビジー待機(スピニング)を費やすことはありません。もちろん、スピンループバックオフと待機のパラメーターのチューニングはハードウェアとワークロードに依存しますが、通常、標準ライブラリには適切な選択肢があります。
ミューテックスとセマフォは同期プリミティブとして使用されますが、それらの間には大きな違いがあります。mutexの場合、mutexをロックまたは取得したスレッドのみがmutexをロック解除できます。セマフォの場合、セマフォで待機しているスレッドに別のスレッドからシグナルを送ることができます。一部のオペレーティングシステムは、プロセス間のミューテックスとセマフォの使用をサポートしています。通常、使用は共有メモリで作成されます。
ミューテックス:クリティカルセクションスレッドT1がアクセスしたい場合、以下の手順に従います。T1:
バイナリセマフォ:シグナル待機とシグナルに基づいて機能します。wait(s)は "s"値を1ずつ減らします。通常、 "s"値は値 "1"で初期化され、信号は "s"値を1つ増やします。「s」値が1の場合、クリティカルセクションを使用していないことを意味し、値が0の場合、クリティカルセクションが使用されていることを意味します。スレッドT2がクリティカルセクションを使用している場合、以下の手順に従います。T2:
MutexとBinaryセマフォの主な違いは、スレッドがクリティカルセクションをロックした場合、Mutextにあり、他のスレッドはクリティカルセクションをロック解除する必要はありませんが、バイナリセマフォの場合、1つのスレッドがwait(s)関数を使用してクリティカルセクションをロックした場合、値「s」の値が「0」になり、「s」の値が1になるまで誰もアクセスできませんが、他のスレッドがシグナルを呼び出して「s」の値が1になり、他の関数がクリティカルセクションを使用できるようになったとします。したがって、バイナリセマフォスレッドには所有権がありません。
Windowsでは、ミューテックスとバイナリセマフォには2つの違いがあります。
mutexは、所有権を持つスレッド、つまり以前にWait関数を呼び出した(または作成時に所有権を取得した)スレッドによってのみ解放できます。セマフォはどのスレッドでも解放できます。
スレッドは、ブロックせずにmutexで待機関数を繰り返し呼び出すことができます。ただし、セマフォを解放せずにバイナリセマフォで待機関数を2回呼び出すと、スレッドはブロックされます。
明らかにmutexを使用して、同時に別のスレッドからアクセスされる1つのスレッドのデータをロックします。呼び出したばかりlock()
で、データにアクセスしていると仮定します。これは、他のスレッド(または同じスレッドコードの別のインスタンス)が同じミューテックスによってロックされた同じデータにアクセスすることを期待しないことを意味します。つまり、別のスレッドインスタンスで実行されている同じスレッドコードである場合、ロックをヒットすると、lock()
そこで制御フローをブロックする必要があります。これは、同じデータにアクセスし、同じミューテックスによってロックされている別のスレッドコードを使用するスレッドに適用されます。この場合、まだデータにアクセスしている最中であり、ミューテックスのロック解除に到達するまでにさらに15秒かかる場合があります(ミューテックスロックでブロックされている他のスレッドのブロックが解除され、コントロールがデータにアクセスします)。何らかの犠牲を払って、別のスレッドが同じミューテックスをロック解除して、ミューテックスロックですでに待機(ブロッキング)しているスレッドがブロックを解除してデータにアクセスできるようにしますか?私がここで言っていることをあなたが理解したことを願っていますか?ごとに、普遍的な定義に同意しました!、
したがって、ミューテックスの代わりにバイナリセマフォを使用することに非常にこだわっている場合は、ロックとロック解除の「スコープ」に非常に注意する必要があります。つまり、すべてのロックにヒットするすべての制御フローは、ロック解除の呼び出しをヒットする必要があります。また、「最初のロック解除」ではなく、常に「最初のロック」である必要があります。
Mutexは「ロックメカニズム」に使用されます。一度に1つのプロセスが共有リソースを使用できます
一方
セマフォは、「信号メカニズム」に使用されます。
神話:
「バイナリセマフォとミューテックスは同じ」または「値1のセマフォはミューテックスである」という記事のカップルによると、他のスレッドからセマフォに信号を送ることができる一方で、ミューテックスはそれを取得したスレッドによってのみ解放できる
キーポイント:
•スレッドは複数のロックを取得できます(Mutex)。
•mutexは、その再帰的mutexの場合にのみ複数回ロックできます。ここで、mutexのロックとロック解除は同じでなければなりません。
•すでにミューテックスをロックしていたスレッドがミューテックスを再度ロックしようとすると、そのミューテックスの待機リストに入り、デッドロックが発生します。
•バイナリセマフォとミューテックスは似ていますが、同じではありません。
•Mutexは、それに関連付けられている保護プロトコルのため、コストのかかる操作です。
•mutexの主な目的は、アトミックアクセスまたはリソースのロックを達成することです
A ミューテックスは、単一の共有リソースへのアクセスを制御します。これは、そのリソースへのアクセスを取得()し、完了時にリリース()する操作を提供します。
A セマフォは、リソースの共有プールへのアクセスを制御します。これは、プール内のリソースの1つが使用可能になるまでWait()、およびプールに戻されたときにSignal()への操作を提供します。
セマフォが保護するリソースの数が1より大きい場合、それはカウントセマフォと呼ばれます。1つのリソースを制御する場合は、ブールセマフォと呼ばれます。ブールセマフォはミューテックスと同等です。
したがって、セマフォはミューテックスよりも高いレベルの抽象化です。ミューテックスはセマフォを使用して実装できますが、その逆はできません。
変更された質問は-「Linux」でのミューテックスと「バイナリ」セマフォの違いは何ですか?
回答:違いは次のとおりです– i)スコープ– mutexのスコープは、それを作成し、スレッドの同期に使用されるプロセスアドレス空間内にあります。一方、セマフォはプロセス空間全体で使用できるため、プロセス間同期に使用できます。
ii)Mutexはセマフォよりも軽量で高速です。Futexはさらに高速です。
iii)mutexは、同じスレッドが同じ回数解放できるという条件で、複数回正常に取得できます。取得しようとする他のスレッドはブロックされます。セマフォの場合、同じプロセスが再度取得しようとすると、一度しか取得できないためブロックされます。
ミューテックスはクリティカル領域のブロックで機能しますが、セマフォはカウントで機能します。
http://www.geeksforgeeks.org/archives/9102 で詳細に議論されています。
Mutex
リソースへのアクセスを同期するために使用されるロックメカニズムです。
Semaphore
信号メカニズムです。
プログラマーがmutexの代わりにバイナリセマフォを使用するかどうかは、プログラマ次第です。
mutexに所有者がいるという事実は別として、2つのオブジェクトは異なる使用法のために最適化される場合があります。mutexは、短時間だけ保持されるように設計されています。これに違反すると、パフォーマンスが低下し、スケジュールが不当になる可能性があります。たとえば、別のスレッドがすでにブロックされている場合でも、実行中のスレッドはmutexの取得を許可される場合があります。セマフォはより公平性を提供するか、いくつかの条件変数を使用して公平性を強制することができます。
sem_post()
for SCHED_FIFO
およびSCHED_RR
(これらは両方ともデフォルトではありません)によって起こされるスレッドの特定の要件があります。優先順位が最も高いスレッド、同じ優先順位のスレッドが複数ある場合は、最も長く待機しているスレッド。OpenSolarisは、通常のスケジューリングであっても、このFIFOルールにある程度従います。glibcとFreeBSDの場合、基本的なミューテックスのロック解除(つまり、優先保護や優先継承ではない)とセマフォのポストは基本的に同じで、オブジェクトをロック解除としてマークし、待機中のスレッドがある場合は、カーネルを呼び出してスレッドを起動します。
バイナリセマフォはミューテックスとして使用できますが、ミューテックスは、ミューテックスをロックしたプロセスだけがロック解除することになっているという点で、より具体的なユースケースです。この所有権の制約により、以下に対する保護を提供できます。
これらの制約は速度を低下させるため、常に存在するとは限りません。コードの開発中に、これらのチェックを一時的に有効にすることができます。
たとえば、ミューテックスでエラーチェック属性を有効にすることができます。EDEADLK
同じものを2回ロックしようとしたEPERM
場合、および自分のものではないミューテックスをロック解除した場合、ミューテックスのエラーチェックは戻ります。
pthread_mutex_t mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init (&mutex, &attr);
初期化したら、これらのチェックを次のようにコードに配置できます。
if(pthread_mutex_unlock(&mutex)==EPERM)
printf("Unlock failed:Mutex not owned by this thread\n");
上記の投稿を読んだ後、コンセプトは私には明らかでした。しかし、いくつかの疑問が残りました。それで、私はこの小さなコードを書きました。
セマフォを使わずに渡そうとすると、それが通り抜けます。ただし、mutexを取得せずに指定しようとすると失敗します。これをWindowsプラットフォームでテストしました。USE_MUTEXを有効にして、MUTEXを使用して同じコードを実行します。
#include <stdio.h>
#include <windows.h>
#define xUSE_MUTEX 1
#define MAX_SEM_COUNT 1
DWORD WINAPI Thread_no_1( LPVOID lpParam );
DWORD WINAPI Thread_no_2( LPVOID lpParam );
HANDLE Handle_Of_Thread_1 = 0;
HANDLE Handle_Of_Thread_2 = 0;
int Data_Of_Thread_1 = 1;
int Data_Of_Thread_2 = 2;
HANDLE ghMutex = NULL;
HANDLE ghSemaphore = NULL;
int main(void)
{
#ifdef USE_MUTEX
ghMutex = CreateMutex( NULL, FALSE, NULL);
if (ghMutex == NULL)
{
printf("CreateMutex error: %d\n", GetLastError());
return 1;
}
#else
// Create a semaphore with initial and max counts of MAX_SEM_COUNT
ghSemaphore = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL);
if (ghSemaphore == NULL)
{
printf("CreateSemaphore error: %d\n", GetLastError());
return 1;
}
#endif
// Create thread 1.
Handle_Of_Thread_1 = CreateThread( NULL, 0,Thread_no_1, &Data_Of_Thread_1, 0, NULL);
if ( Handle_Of_Thread_1 == NULL)
{
printf("Create first thread problem \n");
return 1;
}
/* sleep for 5 seconds **/
Sleep(5 * 1000);
/*Create thread 2 */
Handle_Of_Thread_2 = CreateThread( NULL, 0,Thread_no_2, &Data_Of_Thread_2, 0, NULL);
if ( Handle_Of_Thread_2 == NULL)
{
printf("Create second thread problem \n");
return 1;
}
// Sleep for 20 seconds
Sleep(20 * 1000);
printf("Out of the program \n");
return 0;
}
int my_critical_section_code(HANDLE thread_handle)
{
#ifdef USE_MUTEX
if(thread_handle == Handle_Of_Thread_1)
{
/* get the lock */
WaitForSingleObject(ghMutex, INFINITE);
printf("Thread 1 holding the mutex \n");
}
#else
/* get the semaphore */
if(thread_handle == Handle_Of_Thread_1)
{
WaitForSingleObject(ghSemaphore, INFINITE);
printf("Thread 1 holding semaphore \n");
}
#endif
if(thread_handle == Handle_Of_Thread_1)
{
/* sleep for 10 seconds */
Sleep(10 * 1000);
#ifdef USE_MUTEX
printf("Thread 1 about to release mutex \n");
#else
printf("Thread 1 about to release semaphore \n");
#endif
}
else
{
/* sleep for 3 secconds */
Sleep(3 * 1000);
}
#ifdef USE_MUTEX
/* release the lock*/
if(!ReleaseMutex(ghMutex))
{
printf("Release Mutex error in thread %d: error # %d\n", (thread_handle == Handle_Of_Thread_1 ? 1:2),GetLastError());
}
#else
if (!ReleaseSemaphore(ghSemaphore,1,NULL) )
{
printf("ReleaseSemaphore error in thread %d: error # %d\n",(thread_handle == Handle_Of_Thread_1 ? 1:2), GetLastError());
}
#endif
return 0;
}
DWORD WINAPI Thread_no_1( LPVOID lpParam )
{
my_critical_section_code(Handle_Of_Thread_1);
return 0;
}
DWORD WINAPI Thread_no_2( LPVOID lpParam )
{
my_critical_section_code(Handle_Of_Thread_2);
return 0;
}
セマフォが「リソースを使用して行われる」ことを通知できるという事実自体が、リソースを所有していない場合でも、セマフォの場合、所有とシグナリングの間には非常に疎結合があると思います。
機密コードとデータを保護するためにミューテックスが使用され、同期にはセマフォが使用されます。機密コードを保護することで実際に使用することもできますが、操作Vによって他のスレッドによる保護を解放するリスクがある可能性があります。バイセマフォとミューテックスの違いは所有権です。たとえば、トイレによって、ミューテックスはトイレに入ることができ、ドアをロックできるようなものです。男が降りるまで他の誰も入ることができません。バイセマフォは、そのようなものですトイレとドアをロックしますが、誰かが管理者にドアを開けるように要求することで入ることができるのは、とんでもないことです。
ミューテックス
ミューテックスは通常、複数のスレッドで同時に実行できない再入可能コードのセクションへのアクセスをシリアル化するために使用されます。ミューテックスオブジェクトでは、1つのスレッドのみが制御されたセクションに入ることができ、そのセクションにアクセスしようとする他のスレッドは、最初のスレッドがそのセクションから出るまで待機する必要があります。意図しない副作用。異なる優先順位で動作し、ミューテックスを介して調整する2つのRTOSタスクは、優先順位を逆転させる機会を生み出します。Mutexはユーザー空間で動作します。
セマフォ
セマフォは信号メカニズムです。セマフォは、共有リソースの同時ユーザーの数を最大数に制限します。スレッドは、リソースへのアクセスを要求し(セマフォをデクリメント)、リソースの使用が終了したことを通知できます(セマフォをインクリメント)。これにより、多くのスレッドが共有リソースにアクセスできます。セマフォの正しい使用は、あるタスクから別のタスクへのシグナリング用です。セマフォは、割り込みサービスルーチン(ISR)からタスクへのシグナリングにも使用できます。セマフォのシグナリングはノンブロッキングRTOSの動作であり、したがってISRセーフです。この手法により、エラーが発生しやすいタスクレベルで割り込みを無効にする必要がなくなります。これはカーネル空間で機能します。
答えはターゲットOSによって異なります。たとえば、私が精通している少なくとも1つのRTOS実装では、すべてが同じスレッドコンテキスト内にある限り、単一のOSミューテックスに対して複数の順次「取得」操作を許可します。別のスレッドがmutexを取得できるようにするには、複数のgetを同数のputで置き換える必要があります。 これは、スレッドコンテキストに関係なく、一度に1つのgetのみが許可されるバイナリセマフォとは異なります。
このタイプのミューテックスの背後にある考え方は、一度に1つのコンテキストのみがデータを変更できるようにすることでオブジェクトを保護することです。スレッドがミューテックスを取得し、オブジェクトをさらに変更する関数を呼び出した場合(および独自の操作の周りにプロテクターミューテックスを取得/配置した場合)でも、操作はすべて単一のスレッドで発生するため、安全です。
{
mutexGet(); // Other threads can no longer get the mutex.
// Make changes to the protected object.
// ...
objectModify(); // Also gets/puts the mutex. Only allowed from this thread context.
// Make more changes to the protected object.
// ...
mutexPut(); // Finally allows other threads to get the mutex.
}
もちろん、この機能を使用するときは、1つのスレッド内のすべてのアクセスが本当に安全であることを確認する必要があります。
このアプローチがどれほど一般的であるのか、または私がよく知っているシステムの外部に適用されるのかどうかはわかりません。この種のミューテックスの例については、ThreadX RTOSを参照してください。
mutexは、セマフォとは異なり、所有権を持っています。mutexのスコープ内のスレッドは、ロック解除されたmutexを取得し、コードの同じクリティカルセクションへのアクセスをロックできますが、mutexをロックしたスレッドのみがロックを解除する必要があります。
最良のソリューション
唯一の違いは
1.ミューテックス->ロックとロック解除は、ミューテックスをロックするスレッドの所有権の下にあります。
2.セマフォ->所有権なし。1つのスレッドがsemwait(s)を呼び出す場合、他のスレッドはsempost(s)を呼び出してロックを解除できます。
ミューテックス
最近まで、カーネルでスリープ状態のロックはセマフォだけでした。セマフォのほとんどのユーザーは、カウントを1にしてセマフォをインスタンス化し、それらを相互排他ロック(スピンロックのスリープバージョン)として扱いました。残念ながら、セマフォは汎用的であり、使用上の制約はありません。これにより、カーネルとユーザー空間の間の複雑なダンスなど、あいまいな状況での排他的アクセスの管理に役立ちます。しかし、これはまた、単純なロックは実行が困難であることを意味し、適用されるルールがないため、あらゆる種類の自動デバッグや制約の適用が不可能になります。より単純なスリープロックを求めて、カーネル開発者はミューテックスを導入しました。はい、あなたが今慣れているように、それは紛らわしい名前です。明確にしましょう。「mutex」という用語は、相互排他を強制するスリープ状態のロックを指す総称です。使用回数が1のセマフォなど。最近のLinuxカーネルでは、固有名詞「mutex」も相互排除を実装する特定のタイプのスリープロックになりました。つまり、mutexはmutexです。
ミューテックスのシンプルさと効率は、セマフォが必要とするものに加えて、ミューテックスがユーザーに課す追加の制約に由来しています。Dijkstraの元の設計に従って最も基本的な動作を実装するセマフォとは異なり、mutexにはより厳密で狭い使用例があります。n一度に1つのタスクのみがmutexを保持できます。つまり、ミューテックスの使用回数は常に1です。
[1] Linuxカーネル開発、第3版Robert Love
ここでの答えのほとんどは混乱を招いたと思います。特に、ミューテックスはそれを保持するプロセスによってのみ解放できるが、セマフォはyプロセスによって信号を送ることができると言っているものは混乱していると思います。上記の行は、セマフォに関しては漠然としています。理解するには、セマフォには2種類あり、1つはカウンティングセマフォと呼ばれ、もう1つはバイナリセマフォと呼ばれます。セマフォのカウントでは、n個のリソースへのアクセスを処理します。nは使用前に定義できます。各セマフォには、使用中のリソース数のカウントを保持するカウント変数があり、最初はnに設定されています。リソースを使用したい各プロセスは、セマフォに対してwait()操作を実行します(これにより、カウントが減少します)。プロセスがリソースを解放するとき、それはrelease()操作(カウントをインクリメント)を実行します。カウントが0になると、すべてのリソースが使用されています。その後、プロセスはカウントが0を超えるまで待機します。これが、リソースを保持するプロセスのみがカウントを増やすことができるキャッチです。他のプロセスはカウントを増やすことができません。リソースを保持するプロセスだけがカウントを増やすことができます。セマフォを再度待機してチェックを行い、利用可能なリソースを見つけると、カウントを再び減らします。したがって、バイナリセマフォに関しては、セマフォを保持するプロセスだけがカウントを増やすことができ、セマフォの使用を停止してカウントを増やし、他のプロセスがセマフォにアクセスする機会を得るまで、カウントはゼロのままです。ここで、リソースを保持するプロセスのみがカウントを増やすことができるキャッチがあります。他のプロセスはカウントを増やすことができません再びカウントを減らします。したがって、バイナリセマフォに関しては、セマフォを保持するプロセスだけがカウントを増やすことができ、セマフォの使用を停止してカウントを増やし、他のプロセスがセマフォにアクセスする機会を得るまで、カウントはゼロのままです。ここで、リソースを保持するプロセスのみがカウントを増やすことができるキャッチがあります。他のプロセスはカウントを増やすことができません再びカウントを減らします。したがって、バイナリセマフォに関しては、セマフォを保持するプロセスだけがカウントを増やすことができ、セマフォの使用を停止してカウントを増やし、他のプロセスがセマフォにアクセスする機会を得るまで、カウントはゼロのままです。
バイナリセマフォとミューテックスの主な違いは、セマフォはシグナルメカニズムであり、ミューテックスはロックメカニズムですが、バイナリセマフォはミューテックスのように機能して混乱を招くように見えますが、どちらも異なる種類の作業に適した異なる概念です。