再帰ロック(ミューテックス)と非再帰ロック(ミューテックス) 質問する

再帰ロック(ミューテックス)と非再帰ロック(ミューテックス) 質問する

POSIX では、ミューテックスの再帰が許可されています。つまり、同じスレッドが同じミューテックスを 2 回ロックしてもデッドロックは発生しません。もちろん、2 回ロック解除する必要もあります。そうしないと、他のスレッドはミューテックスを取得できません。pthread をサポートするすべてのシステムが再帰ミューテックスをサポートしているわけではありませんが、POSIX に準拠したい場合は、再帰ミューテックスをサポートする必要があります

他の API (より高レベルの API) も通常、ミューテックス (ロックと呼ばれることが多い) を提供します。一部のシステム/言語 (Cocoa Objective-C など) は、再帰ミューテックスと非再帰ミューテックスの両方を提供します。一部の言語では、どちらか一方のみを提供する場合もあります。たとえば、Java では、ミューテックスは常に再帰的です (同じスレッドが同じオブジェクトで 2 回「同期」する場合があります)。他のスレッド機能によって、再帰ミューテックスがなくても問題ない場合があります。再帰ミューテックスを簡単に自分で記述できるからです (私はすでに、より単純なミューテックス/条件操作に基づいて、再帰ミューテックスを自分で実装しました)。

よくわからないのは、非再帰ミューテックスのメリットは何ですか? 同じミューテックスを 2 回ロックする場合、なぜスレッド デッドロックが必要になるのですか? それを回避できる高級言語 (たとえば、デッドロックするかどうかをテストし、デッドロックした場合は例外をスローする) でも、通常はそうしません。代わりに、スレッドがデッドロックするようになります。

これは、誤って 2 回ロックし、1 回しかロック解除しなかった場合のみに適用されるのでしょうか。再帰ミューテックスの場合は、問題を見つけるのが難しくなるため、代わりにすぐにデッドロックにして、誤ったロックがどこに表示されたかを確認しますか? しかし、ロック解除時にロック カウンターを返し、最後のロックを解放したことが確実でカウンターがゼロでない状況で、例外をスローするか、問題をログに記録することで、同じことはできませんか? または、私が見逃している、非再帰ミューテックスのその他のより有用な使用例はありますか? または、非再帰ミューテックスは再帰ミューテックスよりもわずかに高速であるため、これはパフォーマンスだけの問題でしょうか? ただし、これをテストしましたが、違いはそれほど大きくありませんでした。

ベストアンサー1

再帰的ミューテックスと非再帰的ミューテックスの違いは、所有権に関係しています。再帰的ミューテックスの場合、カーネルは、再帰と、代わりにブロックする必要がある別のスレッドの違いを検出できるように、最初にミューテックスを実際に取得したスレッドを追跡する必要があります。別の回答で指摘されているように、このコンテキストを保存するためのメモリと、コンテキストを維持するために必要なサイクルの両方に関して、追加のオーバーヘッドの問題があります。

ただし、ここでは他の考慮事項も関係しています。

再帰ミューテックスには所有権の感覚があるため、ミューテックスを取得するスレッドはミューテックスを解放するスレッドと同じである必要があります。非再帰ミューテックスの場合、所有権の感覚はなく、どのスレッドが最初にミューテックスを取得したかに関係なく、どのスレッドでもミューテックスを解放できます。多くの場合、このタイプの「ミューテックス」は実際にはセマフォ アクションであり、ミューテックスを排他デバイスとして使用する必要はなく、2 つ以上のスレッド間の同期またはシグナリング デバイスとして使用します。

ミューテックスの所有権の感覚に伴うもう 1 つの特性は、優先度の継承をサポートする機能です。カーネルはミューテックスを所有するスレッドとすべてのブロッカーの ID を追跡できるため、優先度スレッド システムでは、現在ミューテックスを所有しているスレッドの優先度を、現在ミューテックスをブロックしている最も優先度の高いスレッドの優先度にエスカレートすることが可能になります。この継承により、このような場合に発生する可能性がある優先度の逆転の問題が防止されます (すべてのシステムがこのようなミューテックスの優先度の継承をサポートしているわけではありませんが、これは所有権の概念によって可能になるもう 1 つの機能です)。

従来の VxWorks RTOS カーネルを参照すると、次の 3 つのメカニズムが定義されています。

  • ミューテックス- 再帰をサポートし、オプションで優先度の継承もサポートします。このメカニズムは、データの重要なセクションを一貫した方法で保護するためによく使用されます。
  • バイナリ セマフォ- 再帰なし、継承なし、単純な排他、受け取り側と受け取り側が同じスレッドである必要はなく、ブロードキャスト リリースが利用可能。このメカニズムはクリティカル セクションを保護するために使用できますが、スレッド間の一貫したシグナリングや同期にも特に役立ちます。
  • カウント セマフォ- 再帰や継承はなく、任意の初期カウントからの一貫したリソース カウンターとして機能し、スレッドはリソースに対するネット カウントがゼロの場合にのみブロックされます。

繰り返しになりますが、これはプラットフォームによって、特にこれらを何と呼ぶか​​によって多少異なりますが、ここで示されているのは、使用されている概念やさまざまなメカニズムの代表例です。

おすすめ記事