web-dev-qa-db-ja.com

スレッドのスリープはどのように機能しますか?

スレッドをsleepすると、実際には何が起こっていますか?

スレッドをスリープ状態にすると「現在のスレッドが一定期間一時停止します」。しかし、それはどのように機能するのでしょうか?

Thread.sleep()が内部でどのように機能するか および Thread.sleepが実際にどのように機能するか によると:

  • スリープ期間は、システム固有の細分性の影響を受けます
  • 睡眠はブロッキング
  • スレッドはCPUを離れ、その実行を停止します
  • スレッドはスリープ中にCPU時間を消費していません

これが何を意味するのかについての内部および基本的なメカニズムを完全に理解することはできません。

スレッド間の切り替えを担当するschedulerと呼ばれるものがあることを理解しています。

ソースは、これがOS(またはハードウェア)によって異なることを示しているようで、ほとんどのスレッドには、CPUが別のスレッドに切り替える前にいくつかのアクションを実行するために1ミリ秒から60ミリ秒程度与えられています。

しかし、スレッドがスリープ状態になると(たとえば、数秒)、どのように再開しますか?タイマーが何らかの形で関与していると思いますが、それはマザーボードのクロックですか? CPUクロックレートに関連していますか?

タイマーが関係している場合でも、CPUは、スレッドに再び注意を払う時期になったことをどのようにして知るのでしょうか。常にスレッドをチェックインして、準備ができているかどうかを確認する必要はありませんか。それは効果的に ポーリング であり、したがっての種類はCPU時間を消費していませんか?

スレッドは言語固有にスリープしていますか、それともOSが責任を負っていますか、それともCPU固有のものですか?

誰かが、スケジューラなどの基本的な説明と、このすべての間にCPUが実行していることを説明してくれませんか?

13
Rowan Freeman

プログラムの実行には、そのプログラム内のコードだけではなく、もっと多くのことが関係しています。

マルチプロセスOSで実行されるプログラムは、OSのschedulerの制御下にあり、スケジューラは、実行中のプロセス、CPUサイクルが実行されたときに実行を待機しているプロセスを示す明示的なテーブルを維持します利用可能であり、実行しようとしてもいない(スリープ)。スケジューラは通常、優先順位と実行履歴に応じて、プロセスに偶数サイズのタイムスライスを割り当てます。最終的に、このループはハードウェア割り込みによって駆動され、通常はメインボード上の発振器によって生成されます。

スリープは常に、プログラミング言語がサポートできる機能であり、それが実行されるランタイム環境でサポートされているためです。通常のプログラムは一時停止できませんそれ自体、それはどのように処理するかlikeをスケジューラに伝えることができるだけです-スケジューラは決して義務付けられておらず、それを常に満たすことができます願います。ラップトップが閉じられて休止状態に入ると考えてください。メインボードの発振器は脈動し続けますが、スケジューラが実行されていないので、その優先度がどれほど高くても、プロセスは実行できません。

10
Kilian Foth

Doc Brownがコメントで言及しているように、割り込みは重要であり、単に眠るためではありません。

割り込みは、プロセッサが実行していることを停止し、コードを実行する必要のあるハードウェア信号です。外部デバイスは、プロセッサの注意が必要なときに割り込みをトリガーします。たとえば、ディスクがデータの読み取りを終了したとき、キーが押されたとき、マザーボードのカウントダウンタイマーがゼロになったときなどです。

割り込み処理コードは一般に非常に小さく、非常に高速です。たとえば、ブロックがメモリにコピーされたことをディスクが示す場合、OSはその事実をどこかで「準備ができたブロック」のリストに記録し、その後、それが行っていた他の処理に戻る場合があります。 CPUがすべての時間を割り込み処理コードに費やしたり、ユーザーコードを実行したりしたくない場合。

ではないが必ず小さい割り込み駆動型コードの1つがスケジューラです。カウントダウンタイマーからの信号によってトリガーされ、実行されるたびにシステムの状態を調べます。これには通常、実行の準備ができているプロセス(たとえば、それらが待機していたブロックがメモリに到着したため)と、タイムスライスを使い果たしたプロセスの識別が含まれます。

したがって、スレッドスリープを実行すると、OSに(1)タイムスライスをあきらめていること、(2)一定の時間が経過するまで再度起こされないように伝えていることになります。

スケジューラーは、実行されるたびにスレッドを調べ、その時間が経過した場合にのみ「実行可能」とマークします。これは一種のポーリングですが、割り込みによってトリガーされるため、「ビジーループ」ポーリングではありません。また、それほど高価ではありません。通常、一度に実行されるスレッドは1,000個程度です。

これにより、スリープ時間が正確ではない理由がわかります。スレッドが実行可能になると、まだ実行中で他のスレッドがタイムスライスを使い果たしていない可能性があります。または、実行の準備ができている優先度の高いスレッドがある可能性があります。

6
kdgregory