web-dev-qa-db-ja.com

ミューテックスよりも条件変数を使用する利点

Pthreadのミューテックスロックよりも条件変数を使用することのパフォーマンス上の利点は何であるか疑問に思いました。

私が見つけたのは、「条件変数がないと、プログラマーは、条件が満たされているかどうかを確認するために、スレッドを継続的にポーリングする必要があります(おそらくクリティカルセクションで)。これは、スレッドが継続的にビジーになるため、非常にリソースを消費する可能性があります。アクティビティ。条件変数は、ポーリングせずに同じ目標を達成する方法です。」 ( https://computing.llnl.gov/tutorials/pthreads

しかし、(スピンロックとは異なり)ミューテックス呼び出しがブロックされているようにも見えます。したがって、他のスレッド(T2)がロックを持っているためにスレッド(T1)がロックを取得できない場合、T1はOSによってスリープ状態になり、T2がロックを解放してOSがT1にロックを与えたときにのみウェイクアップされます。スレッドT1は、ロックを取得するために実際にはポーリングしません。この説明から、条件変数を使用することによるパフォーマンス上の利点はないようです。いずれの場合も、ポーリングは含まれません。とにかくOSは、条件変数パラダイムが提供できる利点を提供します。

実際に何が起こっているのか説明していただけますか。

26
Abhi

条件変数を使用すると、スレッドに関心のあることが発生したときに、そのスレッドに信号を送ることができます。

ミューテックス自体はこれを行いません。

相互排除が必要な場合は、条件変数は何もしません。ただし、何かがいつ発生するかを知る必要がある場合は、条件変数が役立ちます。

たとえば、作業するアイテムのキューがある場合、さまざまなプロデューサースレッドとコンシューマースレッドがアクセスしたときにキューの内部が一貫していることを確認するためのミューテックスがあります。ただし、キューが空の場合、コンシューマスレッドは、キューが機能するために何かがそこにあることをどのように知るのでしょうか。条件変数のようなものがなければ、キューをポーリングし、ポーリングごとにミューテックスを取得して解放する必要があります(そうでない場合、プロデューサースレッドはキューに何かを置くことができません)。

条件変数を使用すると、消費者は、キューが空のときに、キューに何かが入れられたことを示す条件変数を待つことができることを見つけることができます。ポーリングなし-そのスレッドは、プロデューサーがキューに何かを入れるまで何もしません。その後、キューに新しいアイテムがあることを条件に通知します。

47
Michael Burr

パフォーマンスを求めている場合は、「ノンブロッキング/ノンロック」スレッド同期アルゴリズムについて読み始めてください。それらはアトミック操作に基づいており、gccは親切にも提供してくれます。 gccアトミック操作を検索します。私たちのテストでは、ミューテックスでロックするよりも高速にアトミック操作の大きさを使用して、複数のスレッドでグローバル値をインクリメントできることが示されました。 これは、ロックせずに同時に複数のスレッドからリンクリストにアイテムを追加する方法を示すサンプルコードです。

スレッドのスリープとウェイクアップの場合、シグナルは条件よりもはるかに高速です。あなたが使う pthread_killはシグナルを送信し、sigwaitはスレッドをスリープさせます。これも同じ種類のパフォーマンス上の利点でテストしました。 ここにいくつかのサンプルコードがあります。

5
johnnycrash

ミューテックスと条件変数という、2つの別個の関連するもので重複が多すぎることを探しています。

ミューテックスの一般的な実装アプローチは、フラグとキューを使用することです。フラグは、ミューテックスが誰かによって保持されているかどうかを示し(シングルカウントセマフォも機能します)、キューは、ミューテックスを排他的に取得するために待機しているスレッドを追跡します。

次に、条件変数は、そのミューテックスにボルトで固定された別のキューとして実装されます。ミューテックスの取得を待機するために列に並んだスレッドは、通常、ミューテックスを取得すると、列の先頭から出て、代わりに条件キューに入ることができます。この時点で、2つの別々のウェイターのセットがあります。

  • ミューテックスを独占的に取得するのを待っている人
  • 条件変数が通知されるのを待っている人

ミューテックスを保持しているスレッドが条件変数を排他的に通知する場合、今のところ、それは単一の信号であると想定します(待機しているのは1つだけです。スレッド)ではなくブロードキャスト(待機中のすべてのスレッドを解き放つ)ではなく、条件変数キューの最初のスレッドが(通常は)先頭に戻されますミューテックスキューの。現在ミューテックスを保持しているスレッド(通常は条件変数を通知したスレッド)がミューテックスを放棄すると、ミューテックスキュー内の次のスレッドがミューテックスを取得できます。その次のスレッドは、条件変数キューの先頭にあったスレッドになります。

複雑な詳細がたくさんありますが、このスケッチは、実際の構造と操作の感触を与えるはずです。

5
seh