ほとんどの言語/フレームワークには、スレッドが他のスレッドに制御を渡す方法が存在します。しかし、スレッドから譲歩することが、特定の問題に対する正しい解決策だった時代があったとは思えません。一般に、いつ、、などを使用する必要がありThread.yield()
ますsleep(0)
か?
3 に答える
使用例の 1 つは、並行プログラムのテストです。同期パターンの欠陥を明らかにするインターリービングを見つけてみてください。たとえば、Java では次のようになります。
インターリービングの数を増やして、プログラムの状態空間をより効果的に探索するための便利なトリックは、 を使用
Thread.yield
して、共有状態にアクセスする操作中により多くのコンテキスト スイッチを奨励することです。(JVM は THRead.yield を no-op として自由に処理できるため、この手法の有効性はプラットフォーム固有です [JLS 17.9]。短いがゼロ以外のスリープを使用すると、速度は遅くなりますが、信頼性が高くなります。) — JCIP
また、Java の観点から興味深いのは、それらのセマンティクスが定義されていないことです。
Thread.yield
(および)のセマンティクスThread.sleep(0)
は未定義です [JLS 17.9]。JVM は、それらを no-ops として自由に実装することも、スケジューリングのヒントとして扱うこともできます。特に、Unix システムで sleep(0) のセマンティクスを使用する必要はありません。現在のスレッドをその優先順位の実行キューの最後に置き、同じ優先順位の他のスレッドに譲りますが、一部の JVM はこの方法で yield を実装します。— JCIP
もちろん、これはそれらをかなり信頼できないものにします。これは非常にJava固有のものですが、一般的には次のことが当てはまると思います。
どちらも、スケジューリング順序に影響を与えるために使用できる低レベルのメカニズムです。これを使用して特定の機能を実現する場合、この機能は OS スケジューラの可能性に基づいていますが、これはかなり悪い考えのようです。これは、代わりに高レベルの同期構造で管理する必要があります。
テスト目的またはプログラムを特定の状態に強制するための便利なツールのようです。
あなたのOSスケジューラーにあなたのために決めさせてください?
したがって、sleep(0)が絶対に必要な場合に一致し、ここに文書化するまで、決して譲歩せず、sleep(0)を実行しないでください。
また、コンテキストスイッチはコストがかかるため、コンテキストスイッチを増やしたいと思う人はあまりいないと思います。
一般に、いつ Thread.yield() や sleep(0) などを使用する必要がありますか?
これは、話している VM のスレッド モデルによって異なります。私にとって、答えはめったにありません。
従来、一部のスレッド モデルは非プリエンプティブであり、他のスレッド モデルは成熟していない (または成熟していなかった) ため、Thread.yield()
.
Thread.yield()
これは C での使用に似ていると思いregister
ます。多くの場合、プログラマーはコンパイラーよりも優れているため、プログラムのパフォーマンスを向上させるために C に依存していました。しかし、最新のコンパイラははるかにregister
スマートであり、最近では、プログラマーがおよび を使用してプログラムのパフォーマンスを実際に改善できるケースははるかに少なくなっていますThread.yield()
。