用語を明確にするために、yieldはスレッドがタイムスライスを放棄するときです。私の興味のあるプラットフォームはPOSIXスレッドですが、質問は一般的だと思います。
私が消費者/生産者パターンを持っているとしましょう。消費者と生産者のどちらを使用するか、睡眠するか、譲歩するかを抑制したい場合はどうすればよいですか?私は主にどちらかの機能を使用する効率に興味があります。
用語を明確にするために、yieldはスレッドがタイムスライスを放棄するときです。私の興味のあるプラットフォームはPOSIXスレッドですが、質問は一般的だと思います。
私が消費者/生産者パターンを持っているとしましょう。消費者と生産者のどちらを使用するか、睡眠するか、譲歩するかを抑制したい場合はどうすればよいですか?私は主にどちらかの機能を使用する効率に興味があります。
プロデューサー/コンシューマーをコーディングする「正しい」方法は、コンシューマーにプロデューサーのデータを待たせることです。これは、ミューテックスなどの同期オブジェクトを使用して実現できます。コンシューマーはWait
ミューテックスを使用します。ミューテックスは、データが利用可能になるまで実行をブロックします。次に、プロデューサーはデータが利用可能になるとミューテックスに信号を送り、コンシューマースレッドをウェイクアップして処理を開始できるようにします。sleep
これは、次の両方の観点よりも効率的です。
そうは言っても、ここにあなたが求めた収量対睡眠の分析があります。何らかの理由で出力を待つことが不可能な場合は、このようなスキームを使用する必要があります。
受信しているトラフィックの量によって異なります。データが常に受信および処理されている場合は、yieldを実行することを検討してください。ただし、ほとんどの場合、これにより「ビジー」ループが発生し、ほとんどの時間を不必要にスレッドをウェイクアップして、準備ができているかどうかを確認します。
おそらく、短時間(おそらく、を使用して1秒未満usleep
)スリープするか、ミューテックスなどの同期オブジェクトを使用して、データが利用可能であることを通知することをお勧めします。
睡眠と収量は同じではありません。スリープを呼び出すと、プロセス/スレッドはCPUを別のプロセス/スレッドに指定された時間与えます。
yieldはCPUを別のスレッドに放棄しますが、CPUを待機している他のスレッドがない場合はすぐに戻る可能性があります。
したがって、たとえば定期的にデータをストリーミングする場合など、スロットルする場合は、sleepまたはnanosleepが使用する関数です。
プロデューサー/コンシューマー間の同期が必要な場合は、ミューテックス/条件付き待機を使用する必要があります。
歩留まりの代わりにスリープする理由の1つは、特定のクリティカルセクションで競合が多すぎる場合です。たとえば、2つのロックを取得しようとして、両方のロックで多くの競合が発生したとします。ここでは、睡眠を使用して指数バックオフを採用できます。これにより、失敗した各試行が疑似ランダムにバックオフして、他のスレッドが成功できるようになります。
この状況での降伏は、ランダムなバックオフの可能性がスレッドの枯渇が発生しない可能性を高める可能性があるため、実際にはあまり役に立ちません。
編集:私はこれが必ずしもJava固有ではないことを知っていますが。Javaの実装には、 その時点でのスタイルの問題とThread.sleep(0)
同じ効果があります。Thread.yield()
Javaでは、一部のJVM実装はThread.yield()をno-opとして扱います。つまり、効果がない場合があります。Thread.sleep()を呼び出すことは、必ずしもスケジューラーがCPUを別のスレッドに譲る必要があることを意味するわけではありません。これも実装に依存します。待機中の別のスレッドにコンテキストスイッチする場合もあれば、コンテキストスイッチに関連するコストを償却するためではない場合もあります。