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


14

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

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

Thread.sleep()が内部どのように動作し、Thread.sleepが実際にどのように動作するかによると

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

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

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

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

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

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

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

誰かがスケジューラのようなものの基本的な説明とこれのすべての間にCPUが何をしているのかでこれを私に説明してくれませんか?


2
スリープ状態のスレッドの再起動は、通常は割り込みクロックによって生成されるタイミング割り込みによって機能します。これは、命令を処理するCPUのコア部分とは別のハードウェアコンポーネントです。これにより、ポーリングの必要がなくなります。たぶん、Quoraに関するこの説明でいくつかのことが明らかになるでしょう:quora.com/How-does-threading-work-at-CPU-level
Doc Brown

1
ほとんどのJVMは実際にマルチスレッドを実装していません。それらが行うのは、基盤となるオペレーティングシステムのマルチスレッド機能を使用することだけです。それがどのように機能するかを本当に知りたいのであれば、オペレーティングシステムの設計に関する本がたくさんあります。
ソロモンスロー

回答:


11

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

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

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


これは(一般的に)プロセスに当てはまりますが、スレッドに常に当てはまるとは限りません。スレッドはOSとは独立して実装でき、協調的またはプリエンプティブにすることができます。たとえば、Rubyには「スレッド」に加えて「ファイバー」があります。ルビーファイバーは共同で予定されています。
david25272

確かに、ネイティブスレッドのみがこのように機能します。緑のスレッドは、バイトコンパイルされた言語でプログラムを実行するVMによってスケジュールされます。通常、ネイティブスレッドが使用できない場合、または適切にスレッドセーフではないコードを実行している場合に使用されます(VMは、マルチスレッドプログラムのセマンティクスがOSスケジューラではできない方法で正しいままであることを保証できる場合があります)。
キリアンフォス

7

以下のようドク・ブラウンはコメントで述べたように、割り込みがキーだけではなく、睡眠のためのものです。

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

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

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

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

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

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


これが「最新の」オペレーティングシステムの動作方法です。OS Xより前のWindows 3やMac OSなどの古いオペレーティングシステムでは、プロセスがオペレーティングシステムにyield()制御を行う必要がありました。残念なことに、プログラムがループでスタックしたり、何らかの理由でデッドロックしたりすると、制御が得られず、システム全体がハングします。
david25272

@ david25272-1960年代にプリエンプティブマルチタスクを実行するシステムがあったため、「古い」ではなく「より単純な」という言葉を使用すると思います。また、協調的マルチタスクでは、プロセッサの制御を解放するためにアクティブスレッドが何かを行う必要があることは事実ですが(通常、明示的な利回りではなく、ブロッキングシステムコールを行うことにより)、多くの汎用プログラマがいるとは思いません協調スレッディングモデルのOSを使用する今日の人々。
kdgregory
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.