私は タスクマネージャ を開き、「システム」領域の下を見て、次のことを確認しました。
スレッド:1337
hyper-threading が利用可能な(4つのスレッドを意味する)デュアルコアプロセッサを使用しているので、プロセッサが4つしかないと想定した場合、1000以上のスレッドを持つことができるのはなぜですか。
簡単な答えは、すべてのスレッドが同時に実行されているわけではないということです。詳細については、以下をお読みください。
オペレーティングシステムのタスクスケジューラは、通常、アプリケーションをスケジュールするものと考えられており、これにより、コンピューターが別のタスクを実行しているときに1つのタスクを実行できます。昔は、マルチタスクのリトマステストは、他のことをしながらフロッピーディスクをフォーマットすることでした。 OSを実際にテストしたい場合は、シリアルポートに接続されたモデムを介してファイルをダウンロードしながら、フロッピーディスクをフォーマットします。ハードウェアが意味のある方法で実際に実行するのに十分強力になったので、ビデオの再生が時々そのようなテストでも取り上げられました。 OSのタスクスケジューラがこれらのタスクの実行をスムーズに処理できれば、何でも処理できます。
ただし、タスクスケジューラは実際にアプリケーション(プロセス)をスケジュールするのではなく、 threads をスケジュールします。各アプリケーションには少なくとも1つのスレッドがありますが、多数のスレッドを使用して、実行する作業を関連する部分または独立した部分に分割する可能性があります。たとえば、アプリケーションがユーザーインターフェイスを処理する1つのスレッドを持ち、ユーザーが潜在的に長時間かかる操作(印刷、スプレッドシートの再計算、開発環境の実行など)を開始したときに別のスレッドを作成するのが一般的です。シンボル検索など)。一部のプログラミング環境では、プログラマには見えない程度のスレッドが導入されています。たとえば、 Java および 。NET は、プログラマが直接制御できない別のスレッドで ガベージコレクション を実行する場合があります。新しいスレッドの作成は比較的コストのかかる操作であるため、一部のプログラムでは、早い段階で多数のスレッドを作成してそれらをプールします(そのため、必要になるたびにスレッドを作成する必要はありません)。通常、プレビューを実行するものはすべて別のスレッドで実行されるため、プレビューが生成されている間、UIの残りの部分は応答性を維持します。 など。まとめると、これは、システム上のスレッド数がいつでも簡単にプロセス数の何倍にもなることを意味します。
各スレッドは、考えられるいくつかの状態のいずれかになりますが、最も重要な違いは、 running 、 runnable と待機中状態;用語は少し異なる場合がありますが、それが一般的な考え方です。常に、仮想(ハイパースレッディングおよび類似のテクノロジーのため)CPUコアごとに1つのスレッドのみが running (つまり、マシンコード命令を実行)ですが、任意の数のスレッドが実行できます。 runnable (スケジューラが次に実行を許可するスレッドを決定する必要があるときにCPUを取得する候補であることを意味します) 待機(ブロックとも呼ばれます)スレッドはそれだけで、何かを待っています-最も一般的なケースは、ユーザー、ディスク、またはネットワークI/O(ユーザー入力特に遅いです)。
タスクマネージャーに表示されるスレッド数は、これらのいずれかの状態のスレッドの総数です。たとえば、これを入力しているWindows 7システムでは、現在約70のプロセスが開始されていますが、ほぼ900のスレッドがあります。さまざまなタスクを処理するためのすべてのバックグラウンドプロセスと、それらがどのようにしてそれぞれ多数のスレッドに細分されるかを考えると、これは法外な数ではありません。
プリエンプティブマルチタスクオペレーティングシステムのタスクスケジューラの中核をなす技術的実装の深さについてもう少し詳しく説明すると、通常はある種のハードウェア割り込みフックです。これは、実行する有用な作業がない場合にカーネルがCPUを停止する可能性があることを意味します(これはほぼ間違いなく the の理由の1つであり、Linuxがチェックする理由 HLT
命令 ---ブート時 IA-32 -互換性のあるCPUであり、おそらく他のアーキテクチャでも同様のチェックを行います)、将来的にある程度合理的に決定するという知識で安全です。割り込みが発生し、タスクスケジューラが呼び出されます。 CPUが実行している他の作業(割り込みの背後にある考え方)に関係なく割り込みが発生するため、スケジューラは定期的に実行され、次のタイムスライス中に実行するスレッドを決定する機会を得ます。コンテキストの切り替えは比較的コストがかかるため、通常、(少なくともソースコードを通じて)スケジューラがスレッド間をいかに積極的に切り替えるかを調整することができます。スレッドを切り替えると、システムの応答性が向上しますが、切り替えのオーバーヘッドは、特定のタスクセットを完了するまでの全体的な時間が長くなることを意味します。 fastest システムは、実行中のスレッドが実行できなくなった場合にのみスレッドを切り替えるシステムになります(つまり、何かを待っているときにブロックされたり、ジョブが終了したりする)。 最も応答性の高いシステムは、特定のスレッドがCPU時間を取得する前に待機する平均時間を最小化するため、スケジューラが呼び出されるたびにスレッドを切り替えます。通常、理想的な設定はこれら2つの中間にあり、これらの選択間のトレードオフが、Linuxがカーネル構成を介して複数のスケジューラーといくつかのチューニングパラメーターを提供する理由の1つであると考えられます。
一方、協調的にマルチタスクを実行するOSと環境( Windows 3.x は1つの例です)は、各アプリケーションに依存して、定期的に制御をスケジューラに渡します。通常、それを行うために特別に意図されたAPI関数があり、多くのAPI関数は、ユーザーエクスペリエンスをよりスムーズにするのに役立つため、多くの場合、内部実行フローの一部としてそれを行います。その設計アプローチは、すべてのアプリケーションが正常に動作し、長時間実行される操作(実行時間が数分の1秒を超えることを意味する)中に短い間隔で制御権を譲る限りうまく機能しますが、アプリケーションが詰まることはありません。システム全体。これが、前述のマルチタスクテストでWindows 3.xがうまく機能しなかった大きな理由の1つです。一方、同じハードウェアで同じタスクを実行しているときに OS/2 は楽しそうに散歩しました。アプリケーションは、特定のセクターを書き込むためのフロッピーディスクドライブ、および呼び出しが戻るまでにかかる時間は、実際には測定可能である(数十から数百ミリ秒以上)。プリエンプティブマルチタスクシステムでは、次のスケジュールされた呼び出しでスケジューラが中断し、現在「実行中」のスレッドが実際には書き込み呼び出しによってブロックされていることに注意して、実行可能な別のスレッドに切り替えるだけです。 (実際には少し複雑ですが、それが一般的な考えです。)
プリエンプティブなマルチタスク環境と協調環境の両方で、異なるスレッドが異なる優先順位を持つ可能性もあります。たとえば、通信リンクを介してデータを受信しているスレッドをシステムの時間表示を更新するスレッドよりもタイムリーに実行することがおそらく重要であるため、受信スレッドの優先度は高く、時間表示更新スレッドの優先度は低くなります。 。スレッドの優先順位は、実行を許可するスレッドをスケジューラが決定する際に重要な役割を果たします(たとえば、非常に単純化された)。高い優先順位のスレッドは常に低い優先順位のスレッドの前に実行する必要があるため、たとえ低い場合でも優先度の高いスレッドは実行すべき作業を残していますが、優先度の高いスレッドが実行可能になると、それが優先されます)が、そのような特定のスケジューリングの決定は、基礎となるメカニズムの設計に影響しません。
1037台の車で4車線の高速道路を考えてみてください。
お使いのOSは、多くのサービスで機能するために多くの実行中のプロセスを必要とします。最も単純なグラフィカルプログラムでさえ、マルチスレッドプログラミングが必要です。多くのプログラムが開かれていると考えると、コンピューティング能力のリソースを共有する必要があることがわかります。
タスクマネージャーが表示しているのは、現在のシステム負荷です。 comp仕様が示しているのは、並列実行のために受け入れられている(フロントエンドの)スレッドの数です。ハイパースレッディングとマルチコア機能の違いをあまり考慮せずに、より論理的なフロントエンドスレッドを受け入れることで、システムのパフォーマンスが向上します。
私たちは一歩下がって、自問自答する必要があります。単一のCPUを搭載したコンピュータに、どのようにして2つのスレッドを持たせることができるでしょうか。
スレッドはハードウェアではなくソフトウェアエンティティです。別のスレッドを作成するには、記述子構造やスタックなど、スレッドを構成するオブジェクト用のメモリが必要です。
オペレーティングシステムは、特定の割り込み(タイマー割り込みなど)の内部や、スレッドがオペレーティングシステムを呼び出すときなど、さまざまなタイミングでスレッドを切り替えます。
システムに存在するすべてのスレッドのうち、通常はサブセットのみが一般に「実行可能」と呼ばれる状態にあります。実行可能スレッドは実行に熱心です。それらは実行中か、「実行キュー」に座って、スケジューラによるディスパッチを待機しています。実行できないスレッドは「ブロック」され、リソースの取得または入力の受信を待機しています。または「スリープ」は、入力でブロックされているようなもので、「入力」は時間の経過です。 「コンテキストスイッチ」は、オペレーティングシステムのスケジューラ機能がプロセッサの実行キューを調べ、実行する別のスレッドを選択するときに発生します。
"hyperthreading" と混同しないでください。これは、特定のハードウェア機能に対するIntelの名前です。