2017-12-24 17 views
10

私はこのようなことについて尋ねるのが最善だろうと思っていたので、Meta(https://meta.stackexchange.com/questions/304981)でこの質問をしました。absl :: Mutexの条件付きクリティカルセクションでリーダーウェイクアップを処理する方法

absl::Mutexhttps://github.com/abseil/abseil-cpp/blob/master/absl/synchronization/mutex.h)という条件付きクリティカルセクションの実装には、どのような最適化が組み込まれているのか本当に不思議でした。特に、私は読者の状態が真実になったときに読者の起床をどのように処理するのだろうと思っていました。彼らはまた待機リストの他のすべての読者を目を覚ますか? This lineは、彼らがそうであることを示すようです。O(n)が毎回横断する危険性がなく、また書き込み優先権のミューテックスで群れを雷鳴する危険性はありませんか?

+0

mutex.ccのインクルードファイルを読んだだけで、pthreadまたはwindow.hが使用されていることがわかります。その高水準のスレッドライブラリでは、おそらく何も魔法を行うことはできません。それが何であれ、スレッドを起こすシステムです。より低いレベルのコードでは、読者が目を覚ますように制御することができます(あるいは少なくともいくつかを選んで 'man 2 futex'を見てください)。このラッパーをラッパーの周りで読むことは、サブレイヤーがなければ存在しない問題を解決するために存在するスーパーレイヤーであなたの時間を無駄にしないでください! – Oliv

+0

'futex'(on linux)は、可能なものの宇宙を拘束するものです。それから、何か(ミューテックス、セマフォーなど)の周りに何かが構築されます。 – Oliv

答えて

4

私は設計と実装の最適化の違いを説明することが重要だと思います。 absl ::は、より最適化されたコンポーネントを提供するのではなく、それらのデザインをサポートする実装を提供することにより、より良いデザインに優先順位を与えているようです。時には、優れたデザインは、不器用なデザインよりも本質的に優れたパフォーマンスであるため、結果は両方の要因(シナジー)で最適化されます。 Absiel.ioがこれについて詳しく説明します。

源泉を見ると、abslは保留中の読者にブロードキャストするのを避けるためにmagicを試行していないようです。したがって、雷の群れは依然として問題です。一般的に、その問題を意味のある方法で解決できる実装はありません。それは設計上の問題です。

ロックの一部として条件を埋め込むことにより、プログラマーはその問題を回避または回避できます。まだ群がありますが、ロックの実装はそれを細くすることができます plan 9 nod here。マスクのビットなど、目を覚ます理由を設計した場合、パフォーマンスに影響を及ぼす偽の起床を心配することなく安全に共有ロックまたは排他ロックを使用できます。

これは「設計の最適化」の本質である:問題がより明確に、ソースに記述し、その結果の実装は、そうでない場合よりも高品質(パフォーマンス、スケーリング、...)のです。

Plan9。条件変数は、スリープ(時間1ではなく)と起床のunixカーネル概念に相当します。オブジェクトが必要な状態にないことを検出すると、その状態にするためのアクションを実行し、その状態が達成されるまで待機します。たとえば、キャッシュ内のオブジェクトをルックアップし、見つからない場合は無効なオブジェクトを作成し、それを有効にするように要求することができます。これにより、すべてのキャッシュ参加者間で一種の対称性が可能になります。オブジェクトをロックし、状態を評価または更新した後、同時にオブジェクトのロックを解除し、さらに変更を待機します。

醜い問題は、同時にこのようなことがなく、b:ロック処理がエラーを起こしやすいということです(他のロックを保持していますか?これがデッドロックにつながる可能性がありますか? 。 Plan9のスリープとウェイクアップはこれらをうまくマージしました。そのため、条件がチェックされた時点で誰もがそのオブジェクトに影響を与えることはできません。実際、参照されている論文の要点は、単純な契約を実施することがどれほど難しいかです。複数の処理環境での複雑な契約は避けることをお勧めしますfor example

ABSL :)に重要な最適化は、(その後、スリープ状態に戻って、オブジェクトが誤った状態にあることを決定するために、高価なコンテキストスイッチ操作を通過する必要がないことです。目を覚ますことを選択しているコードが、オブジェクトの状態があなたが興味を持っている可能性のあるものであることを確認できれば、それほど良いことはありません。関数呼び出し/メソッド呼び出しは、コンテキストスイッチより100倍高速です。

abslThis sectionは、目覚めの候補者がどのように選択され、どのように群れが淘汰されるかの両方に対処する。 This sectionがブロードキャストを生成します。

したがって、前のセクションでは、リストの要素をウェイターから選択し、後者のセクションでウェイクアップします。 2203行目のelse条件を見ると、ライターがリストをどのように終了するかが表示されます。w_walk-> wakeは真ではなく、wr_waitが設定されています。さらに、2015年と2023年の以前のテストでは、書き込みウェイクアップの場合にこのリストを作成することができません。

モニター

obj.enter(); 
while (obj.state != StateIWant) { 
    obj.wait(); 
} 
... 
obj.exit(); 

ガード条件を実行するために、このスレッドが必要です。このブロックされたスレッドを動かす動作は、条件を実行するコストの1000倍になる可能性があります。これとは対照的に:

obj.wait(^{return obj.state == StateIWant;}); 
... 
obj.exit(); 

は無駄な例では、高価なコンテキストスイッチを回避、(。すなわち、出口を呼び出す)の待機を許可された方のスレッドのコンテキストで条件を評価するために待機コールを可能にするであろう。

+0

"指定されたwaker"の機能がコード内でどのようなものになっているのでしょうか? https://github.com/abseil/abseil-cpp/blob/be40fdf1a86f4956d2f8125a7b6bd6d34e133c2d/absl/synchronization/mutex.cc#L593スレッドがどのように目を覚ますかと関係があると思います – Curious

+0

誰かのためにドアを開いたことがありますか一行の人々のためにドアを持っているのが分かりましたか?私が正しくそれを読んでいるなら、それはちょっとです。この場合、ドアは基本的な同期サービス(Futex、Win32、SEMなど)であり、コードはパフォーマンスを向上させるためにコードを回避しようとしています。それは、私はこの事件が起こった場合を想像することができないと言われていますが、私は時には人々の行のためにもドアを持っています。 – mevets

関連する問題