web-dev-qa-db-ja.com

プリエンプティブスレッドと非プリエンプティブスレッド

誰かがプリエンプティブスレッドモデルと非プリエンプティブスレッドモデルの違いを説明できますか?

私の理解に従って:

  • 非プリエンプティブスレッドモデル:いったんスレッドが開始されると、それを停止することはできません。スレッドはそのタスクを完了しました。
  • プリエンプティブスレッディングモデル:ランタイムは、いつでも1つのスレッドから別のスレッドに制御を移すことができます。優先度の高いスレッドは、優先度の低いスレッドよりも優先されます。

誰かがお願いできますか:

  1. 理解が正しいか説明してください。
  2. 両方のモデルの長所と短所を説明します。
  3. 本当に役立つものをいつ使用するかの例。
  4. Linux(システムvまたはPthread)でオプションを指定せずにスレッドを作成した場合(何かありますか?)デフォルトで使用されるスレッドモデルはプリエンプティブスレッドモデルですか?
54
Alok Save
  1. いいえ、あなたの理解は完全に正しいわけではありません。非プリエンプティブ(別名:協調)スレッドは通常、手動で制御を譲り、他のスレッドが完了する前に実行できるようにします(それを実現するのはyield()(または何でも)を呼び出すのはそのスレッド次第です。
  2. スレッドの横取りはより簡単です。協調スレッドはオーバーヘッドが少なくなります。
  3. 通常はプリエンプティブを使用します。デザインにスレッド切り替えのオーバーヘッドが多いことがわかった場合は、協調スレッドが最適化の可能性があります。多くの(ほとんど?)状況では、これはかなりの投資ですが、最低限の見返りがあります。
  4. はい、デフォルトではプリエンプティブスレッドが使用されますが、CThreadsパッケージを探すと、協調スレッドがサポートされます。 (今のところ)協力的なスレッドを望んでいる人はほとんどいませんが、このスレッドが過去10年間に更新されたかどうかはわかりません...
35
Jerry Coffin

非プリエンプティブスレッドは、協調スレッドとも呼ばれます。これらの例はPOE(Perl)です。別の例は、クラシックなMac OS(OS Xより前)です。協調スレッドは、あきらめるまでCPUを排他的に使用します。次に、スケジューラは別のスレッドを選択して実行します。

プリエンプティブスレッドは、協調スレッドと同じように自発的にCPUを放棄することができますが、そうしない場合は、CPUから奪われ、スケジューラーは別のスレッドを開始します。 POSIXおよびSysVスレッドはこのカテゴリに分類されます。

協調スレッドの大きな利点は、効率が向上し(少なくともシングルコアマシンで)、並行性の処理が容易になることです。制御を放棄する場合にのみ存在するため、ロックは必要ありません。

プリエンプティブスレッドの大きな利点は、フォールトトレランスが向上することです。単一のスレッドが生成に失敗しても、他のすべてのスレッドの実行が停止するわけではありません。また、複数のスレッドが同時に実行されるため、通常はマルチコアマシンでより適切に機能します。最後に、あなたが絶えず降伏していることを確認することについて心配する必要はありません。これは、非常に厄介なことです。たとえば、大量の処理ループです。

もちろん、それらを混ぜることもできます。単一のプリエンプティブスレッドでは、その内部で多数の協調スレッドを実行できます。

22
derobert

non-preemptiveを使用しても、プロセスがI/Oを待機しているときにプロセスがコンテキストの切り替えを実行しないわけではありません。ディスパッチャは、スケジューリングモデルに従って別のプロセスを選択します。プロセスを信頼する必要があります。

非プリエンプティブ:

  1. 少ないコンテキスト切り替え、少ないオーバーヘッド非プリエンプティブモデルで賢明な場合があります

  2. シングルコアプロセッサで処理できるため、処理が簡単

プリエンプティブ

利点:

  1. このモデルでは、実行中のプロセスをより詳細に制御するのに役立つ優先順位があります

  2. 同時実行性の向上は跳ね返ります

  3. システム全体をブロックせずにシステムコールを処理する

欠点:

  1. 同期にはより複雑なアルゴリズムが必要で、クリティカルセクションの処理は避けられません。

  2. それに伴うオーバーヘッド

8
pooria

cooperative(non-preemptive)モデルでは、スレッドに制御が渡されると、明示的に制御が渡されるかブロックされるまで実行が継続されます。

プリエンプティブモデルでは、仮想マシンは、いつでも1つのスレッドから別のスレッドに制御を移すことができます。どちらのモデルにも長所と短所があります。

Javaスレッドは一般に、優先度の間で優先されます。優先度の高いスレッドは、優先度の低いスレッドよりも優先されます。優先度の高いスレッドがスリープまたはブロックした場合、優先度の低いスレッドを実行できます(利用可能なスレッドがあり、実行の準備ができていると想定)。

ただし、優先度の高いスレッドが起動またはブロック解除されるとすぐに、優先度の低いスレッドが中断され、終了するか、再びブロックされるか、さらに優先度の高いスレッドによって横取りされるまで実行されます。

Java言語仕様では、VMが実行可能な優先度の高いスレッドではなく、優先度の低いスレッドを実行できる場合がありますが、実際にはこれは異常です。

ただし、Java言語仕様では、同等の優先度のスレッドで何が起こるかを指定していません。一部のシステムでは、これらのスレッドはタイムスライスされ、ランタイムは特定の時間を割り当てます。その時間が終了すると、ランタイムは実行中のスレッドをプリエンプトし、同じ優先順位を持つ次のスレッドに切り替えます。

他のシステムでは、実行中のスレッドが優先されず、同じ優先度のスレッドが優先されます。ブロックするか、明示的に制御を渡すか、優先順位の高いスレッドによって横取りされるまで、実行を続けます。

利点に関しては、デロベルトとプオリアの両方がそれらを非常にはっきりと強調しています。

1
Amimo Benja