なぜほとんどのミューテックス実装は不公平なのですか?


11

私の理解では、mutexの最も一般的な実装(たとえば、C ++のstd :: mutex)は公平性を保証していません-つまり、競合のインスタンスで、ロックがスレッドの順序で取得されることを保証していません lock()と呼ばれます。実際には、(できれば一般的ではありませんが)競合が多い場合に、mutexの取得を待機しているスレッドの一部がmutexを取得できない可能性さえあります。

これは私には役に立たない振る舞いのようです-公平なミューテックスは、プログラマーが望んでいる/期待することにより一致した振る舞いをもたらすように思えます。

mutexが通常公平に実装されない理由は「パフォーマンス」ですが、それが何を意味するのかを理解したいと思います。特に、mutexの公平性要件を緩和すると、パフォーマンスがどのように向上しますか?「フェアな」ミューテックスを実装するのは簡単なようです-スレッドをスリープ状態にする前に、lock()がミューテックスのリンクリストの末尾に呼び出しスレッドを追加し、次にロック解除()で次のスレッドをポップしてくださいその同じリストの頭とそれを目覚めさせます。

ここで見逃しているミューテックス実装の洞察は、より良いパフォーマンスのために公平性を犠牲にすることが価値があると考えられた理由を説明していますか?


1
すべてのミューテックスのリンクリストは、共有データ構造である必要がありますよね?では、パフォーマンスを低下させることなく、データの競合をどのように防ぐのでしょうか。
user3543290 2017

ロックレスリンクリストメカニズムを使用すると思います。起動する次のスレッドを見つけるために、不公平なmutexはどのデータ構造を使用しますか?
Jeremy Friesner、2017

1
あなたはそれを調べる必要がありますが、ロックのないリンクされたリストは公平性を保証しますか?並行プログラミングの公平性などの保証は困難であることがわかると思います。
user3543290 2017

回答:


7

Jim Sawyerの答えは1つの答えを指しています。優先順位の異なるスレッドがある場合、「公平な」動作は正しくありません。実行可能なスレッドが複数ある場合、通常、最も優先度の高いスレッドが実行されるべきスレッドです。

ただし、オペレーティングシステムの実装については少しだけ議論されている秘密があります。これは、オペレーティングシステムがユーザースレッドをハイジャックしてユーザーとしてコードを実行する場合があることです。安全上の理由から、これを行うほとんどのオペレーティングシステムは、スレッドがブロックされているときにのみそれを行います。オペレーティングシステムが完了すると、スレッドは再一時停止されます。これにより、通常、スレッドが待機キューの後ろに移動されます。

典型的な例は、Unixのシグナルハンドラ、VMSの非同期システムトラップ、またはWindows NTの非同期プロシージャコールです。これらはすべて本質的に同じものです。オペレーティングシステムは、何らかのイベントが発生したことをユーザープロセスに通知する必要があり、これはユーザー空間でコードを実行することによって処理されます。

非同期I / Oなどの多くのオペレーティングシステムサービスは、この機能の上に実装されることがよくあります。

別の例は、プロセスがデバッガーの制御下にある場合です。その場合、デバッグシステムは、さまざまな理由でユーザータスクとしてコードを実行することがあります。


4

「優先順位の逆転」は、公平性が望ましくない場合がある1つの理由です。優先度の低いプロセスは、ロックされたミューテックスにヒットしてスリープします。次に、優先度の高いプロセスがヒットし、スリープ状態になります。mutexのロックが解除されると、次にロックを取得するプロセスはどれですか。


このサイトへようこそ。しばらくの間回答がなかった質問に回答していただきありがとうございます。もちろんあなたの答えは正しいですが、もう少し詳しく説明できると思います。
David Richerby 2017

3

フェアミューテックスは、フェアライフミューテックスよりもロックされたライフタイムの多くを費やします。不当なmutexを解放するスレッドは、常にロックを解除できるからです。ただし、フェアミューテックスを解放するスレッドは、ウェイターキューが空の場合にのみロックを解除できます。それ以外の場合、解放スレッドは次のスレッドのためにミューテックスをロックしたままにする必要があります。これは、ウェイターキューの最初のスレッドとも呼ばれ、キューから取り出されて呼び起こされます。ミューテックスは、少なくとも新しく起動されたスレッドがCPUでスケジュールされるまでロックされたままです。現在実行可能なスレッドが多数ある場合は、長時間かかる可能性があります。

また、解放するスレッドがすぐに同じミューテックスを再取得しようとする場合は、それ自体をウェイターキューの後ろに入れて、スリープ状態にする必要があります。スレッドが最初にミューテックスを解放しなかった場合、これは起こりませんでした。したがって、これにより、「より貪欲な」クリティカルセクションが長くなります。

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