並行性はマルチスレッド(PHPのマルチプロセス並行性など)に依存する必要はありませんが、Javaでの並行性について言えば、それらのほとんどはスレッドから切り離せません。
スレッドの実装
スレッドは、CPUスケジューリングの基本単位です。スレッドクラスは、ほとんどのJava APIとは大きく異なります。そのすべての主要なメソッドはネイティブとして宣言されています。つまり、このメソッドは使用されないか、プラットフォームに依存しない手段を使用して実装できません。
カーネルレバースレッド(KLT)
オペレーティングシステムのカーネル(Kermel、以下カーネルと呼びます)が直接サポートするスレッドは、カーネルによって切り替えられます。カーネルは、スケジューラ(Sheduler)を操作してスレッドをスケジュールし、スレッドのタスクを各プロセッサにマッピングします。
各カーネルスレッドはカーネルのアバターと見なすことができるため、OSは同時に複数の処理を行うことができ、複数のスレッドをサポートするカーネルはマルチスレッドカーネル(マルチスレッドカーネル)と呼ばれます。
通常、プログラムはKLTを直接使用せず、KLTを使用する高レベルのインターフェイスは、通常説明するスレッドであるライトウェイトプロセス(LWP)です。各LWPはKLTによってサポートされているため、したがって、最初にKLTをサポートすることによってのみ、LWPが存在できます。この1対1の関係はと呼ばれ一对一的线程模型
ます。
-
制限事項
これはKLTに基づいているため、作成、構造解除、同期などのさまざまなスレッド操作にはシステムコールが必要です。システムコールのコストは比較的高く、ユーザーモードとカーネルモードを切り替える必要があります。次に、各LWPはKLTサポートを必要とするため、LWPは特定のカーネルリソース(KLTスタックスペースなど)を消費するため、システムでサポートされるLWPの数は制限されます。
ユーザースレッド
さまざまな詳細の作成、切り替え、およびスケジューリングはすべて、考慮する必要があります。実装とその難しさは、ユーザースレッドと軽量プロセスを混在させるためにjavaやrubyなどの言語によって放棄されました。
Javaスレッドの実装
ユーザースレッドは依然としてユーザー空間に完全に組み込まれているため、ユーザースレッドの作成、切り替え、破棄などの操作は依然として安価であり、大規模なユーザースレッドをサポートできます。同時実行オペレーティングシステムでサポートされる軽量プロセスは、ユーザースレッドとカーネルスレッドとして使用されます。それらの間のブリッジは、カーネルによって提供されるスレッドスケジューリング関数とプロセッサマッピングを使用でき、ユーザースレッドのシステムコールは軽量スレッドによって完了する必要があります。これにより、プロセス全体が完全にブロックされるリスクが大幅に減少します。
この混合モードでは、軽量プロセスに対するユーザースレッド数の比率は不明確です。つまり、N:Mの間の関係です。Solaris、HP-UXなどの多くのUN1Xシリーズオペレーティングシステムは、N:Mスレッドを提供します。モデルの実装。
Javaスレッド
JDK 1.2より前は、「Green-Threads」と呼ばれるユーザースレッド実装に基づいていました。JDK1.2では、オペレーティングシステムのネイティブスレッドモデルに置き換えられました。したがって、現在のJDKバージョンでは、オペレーティングシステムは何をサポートしていますか?スレッドモデルは、主にJava仮想マシンのスレッドがどのようにマップされるかを決定します。異なるプラットフォームで合意する方法はありません。仮想マシンの仕様は、Javaスレッドが達成するために使用する必要があるスレッドモデルを制限しません。 。
スレッドモデルは、スレッドの同時実行サイズと運用コストにのみ影響し、これらの違いはJavaプログラムのコーディングと実行に対して透過的です。
Siun JDKの場合、そのWindowsおよびLinuxバージョンは1対1のスレッドモデルを使用して実装されます。WindowsおよびLinuxシステムによって提供されるスレッドモデルは1つであるため、Javaスレッドは軽量プロセスにマップされます。 1対1およびSolarisプラットフォームでは、オペレーティングシステムのスレッド特性により、1対1をサポートできます(バインドされた
Threaidsまたは代替Libthread)および多対多(LWP /スレッドベースの同期による)
スレッドモデルの実装)。JDKのSolarisバージョンには、プラットフォーム固有の2つの仮想peachパラメータも用意されています。
-XX:+ UseLWPSynchronization(デフォルト)および-XX:+ UseBoyndThreadsは、仮想マシンが使用するスレッドモデルを明示的に指定します。
Javaスレッドのスケジューリング
-
スレッドのスケジューリング
システムによってスレッドにプロセッサ使用権を割り当てるプロセス。2つの主要なスケジューリング方法があります。
-
協調スレッド-スケジューリング
-
プリエンプティブスレッド-スケジューリング
協調スケジューリングを使用するマルチスレッドシステムでは、スレッドの実行時間はスレッド自体によって制御され、スレッドが作業を実行した後、システムに積極的に通知して別のスレッドに切り替える必要があります。
協調マルチスレッド
-
最大のメリット
実装は単純であり、スレッドはスレッドを切り替える前に独自の処理を行う必要があるため、切り替え操作はスレッドに認識されるため、スレッドの同期の問題はありません。
-
欠点も明らかです
スレッドの実行時間は制御できません
プリエンプティブスケジューリングを備えたマルチスレッドシステムを使用すると、各スレッドにはシステムによって実行時間が割り当てられ、スレッドの切り替えはスレッド自体によって決定されません。このように、スレッドスケジューリングでは、システム制御可能なJavaスレッドスケジューリングのスレッド実行時間方法はプリエンプティブスケジューリングです。Javaスレッドスケジューリングはシステムによって自動的に行われますが、システムが特定のスレッドにより多くの実行時間を割り当てることを「提案」できます。これは、スレッドの優先順位を設定することによって行うことができます。Java言語では、合計10レベルのスレッド優先度(Thread.MIN_PRIORITYからThread.MAX_PRIORITY)が設定されています。2つのスレッドが同時にReady状態にある場合、優先度の高いスレッドがシステムによる実行用に選択されやすくなります。
Javaスレッドはシステムのネイティブスレッドにマッピングすることで実装されるため、スレッドのスケジューリングは最終的にOSに依存します。現在、多くのOSがスレッドの優先度の概念を提供していますが、Javaスレッドの優先度に必ずしも対応していません。 Solarisには2147483648(232)の優先順位がありますが、Windowsには7つしかありません。これは、Javaスレッドの優先順位が高いシステムよりも優れています。中央にスペースを残すことをお勧めしますが、Javaスレッドの優先順位が低いシステムよりも劣ります。優先順位が同じであるいくつかの状況があり、一部のプラットフォームでは異なる優先順位が実際に同じになるだけでなく、優先順位にあまり頼りきれない他の状況もあります。優先順位はシステムの影響を受ける可能性があります自分で変更してください。
たとえば、Windowsシステムには「優先ブースティング」(Priority Boosting)があります。もちろん、
Closed)関数、その一般的な目的は、スレッドが特に「熱心に」実行していることをシステムが検出した場合、スレッドの優先度を超えて実行時間を割り当てることです。したがって、プログラムで優先度を使用して、ステータスが[準備完了]のスレッドのグループを最初に実行するかどうかを正確に決定することはできません。