プロセスとスレッドの違い
- プロセスはメモリスペースを排他的に占有し、それぞれの実行状態を保存し、相互に干渉せず、相互に切り替えることができるため、同時処理タスクの可能性を提供します。
- プロセスのメモリリソースを共有し、相互に高速に切り替えることで、よりきめ細かいタスク制御がサポートされるため、プロセス内のサブタスクを同時に実行できます。
プロセスはリソース割り当ての最小単位であり、スレッドはCPUスケジューリングの最小単位です
- プロセスに関連するすべてのリソースは、PCB(プロセス制御ブロック)に記録されます。
- プロセスはプリエンプティブプロセッサのスケジューリングユニットです。スレッドはプロセスに属し、そのリソースを共有します。
- スレッドは、スタックレジスタ、プログラムテクノロジ、およびTCB(スレッド制御ブロック)のみで構成されます。
プロセスとスレッドの違い
- スレッドは独立したアプリケーションと見なすことはできず、プロセスは独立したアプリケーションと見なすことができます
- プロセスには独立したアドレス空間があり、相互に影響を与えることはありません。スレッドはプロセスの異なる実行パスにすぎません。
- スレッドには独自のスタック変数とローカル変数がありますが、独立したアドレス空間はありません。マルチプロセスプログラムはマルチスレッドプログラムよりも堅牢です。
- プロセスの切り替えはスレッドの切り替えよりもコストがかかり、変数を共有することはできません
Javaプロセスとスレッドの関係
- Javaは、プロセスやスレッドなど、オペレーティングシステムによって提供される機能をカプセル化します。
- プログラムを実行すると、少なくとも1つのスレッドを含むプロセスが生成されます
- 各プロセスはjvmインスタンスに対応し、複数のスレッドがjvmのヒープを共有します
- Javaは自動的にメインスレッドを作成し、メインスレッドは子スレッドを作成できます
スレッドステータス
- 新規:作成後に開始されていないスレッド状態
- 実行可能:実行中(実行中の可能性があり、CPUが実行時間を割り当てるのを待機する可能性がある)と準備完了(CPU使用権を取得するためにスレッドスケジューリングによって選択されるスレッドプールで待機中)が含まれます
- 無期限に待機中(待機中):CPU実行時間は割り当てられないため、ディスプレイをスリープ解除する必要があります。
次のメソッドにより、スレッドは無期限に待機します。- Timeoutパラメーターを設定するObject.wait()メソッドはありません。
- Timeoutパラメーターを設定するThread.join()メソッドはありません
- LockSupport.park()メソッド
- 期限待ち:システムは一定期間後に自動的にウェイクアップします
- ブロッキング:排他ロックの取得を待機中
- 終了:終了したスレッドの状態、スレッドは実行を終了しました
睡眠と待機の違い
- sleepはThreadクラスのネイティブメソッドであり、waitはObjectのネイティブメソッドです。
- sleep()メソッドはどこでも使用できます
- wait()メソッドは、
synchronized
メソッドまたはsynchronized
ブロックでのみ使用できます - Thread.sleepはCPUを放棄するだけで、すでに占有されているロックされたリソースを解放しません。
- Object.waitは、CPUを放棄するだけでなく、占有されていた同期リソースロックを解放します。
notifyとnotifyAllの違い
ロックプールEntryList:
スレッドAがすでにオブジェクトのロックを所有しており、他のスレッドBがこのオブジェクトの同期メソッド(またはブロック)を呼び出したい場合、オブジェクトロックの所有権を取得する必要があり、ブロックされてオブジェクトロックを入力しますプールはロックが解除されるのを待ちます。
待機プールWaitSet:
スレッドがオブジェクトの待機()メソッドを呼び出し、スレッドAがオブジェクトロックを解放し、スレッドAがオブジェクトの待機プールに入ると仮定します。スレッドプール待機ロックは競合オブジェクトではありません。
notifyAll
内のすべての聞かせて待機中のプールのスレッドがすべて入力されたロック・プールのロックを獲得するために競争する機会を。notify
ロックを取得するために競合するロックプールのチャンスに、待機中のスレッドプール内のをランダムに選択します。
産出()
- Thread.yield()関数が呼び出されると、現在のスレッドがCPUを放棄する意思があるというヒントがスレッドスケジューラに与えられますが、スレッドスケジューラはこの暗い時間を無視する場合があります。
- 現在のスレッドがCPUを放棄した場合でも、CPUをプリエンプトし続けます。
- すでに取得されているロックを放棄しません
割り込み()
Thread.currentThread().interrupt();
スレッドを中断する必要があることを通知するための呼び出し
- スレッドがブロック状態にある場合、スレッドはすぐにブロック状態を終了し
InterruptedException
、例外をスローします。 - スレッドが通常のアクティブ状態にある場合、スレッドの割り込みフラグはtrueに設定されます。割り込みフラグが設定されているスレッドは引き続き正常に実行され、影響を受けません。
スレッドを中断する方法。というスレッド
ニーズが呼び出されるが、割り込みに協力しなければならない
。3.タスクは常にスレッドの割り込みフラグビットを確認してください。割り込みフラグビットがセットされている場合、正常に動作している場合
、それはなります停止スレッド自体。4。スレッドが通常のアクティブ状態にある場合、このスレッドの割り込みフラグはtrueに設定されます。ただし、スレッドは正常に実行されます。
ロック
ミューテックスの特徴
相互排除:つまり、マルチスレッド調整メカニズムを実現するこの機能により、1つのスレッドのみが特定のオブジェクトロックを同時に保持できます。相互排除は、操作のアトミック性とも呼ばれます。
可視性:ロックが解放される前に共有変数に加えられた変更が、その後ロックを取得する別のスレッドに表示されることを確認する必要があります(つまり、最新の共有変数の値は、ロックの取得時に取得する必要があります)。
同期
同期されたJDK初期バージョン
- Synchronizedはヘビーウェイトロックであり、MutexLockを使用して実現します
- スレッド間の切り替えは、ユーザーからコアモードに変更する必要があります。これは比較的コストがかかります。
同期jdk6
は、同期の4つの状態(ロックなし、部分ロック、軽量ロック、重量ロック)を最適化します。
バイアスされたロック(ロックにマルチスレッドの競合がない場合)は、同じスレッドによるロックの取得コストを削減します。
基本的な考え方:スレッドがロックを取得すると、ロックはバイアスモードになります。スレッドが再度ロックを要求すると、同期操作を行う必要はありません。つまり、ロックを取得するプロセスでは、Mark Wordのロックマークビットがバイアスされたロックであり、現在のスレッドIDがMarkWordのThreadIDと等しいことを確認するだけで済みます。ロックアプリケーションに関連する多くの操作。
軽量ロックバイアスされたロックは、1つのスレッドが同期ブロックに入ると実行され、2番目のスレッドがロック競合に参加すると、バイアスされたロックが軽量ロックにアップグレードされます。シナリオ:スレッドは同期ブロックを交互に実行します
ヘビー級ロック同時にマルチスレッドの競争がある場合は、ヘビー級ロックにアップグレードしてください
ロックメモリのセマンティクス
- スレッドがロックを解放すると、Javaメモリモデルは、スレッドに対応するローカルメモリ内の共有変数をメインメモリにフラッシュします。
- スレッドがロックを取得すると、Javaメモリモデルはスレッドに対応するローカルメモリを無効にするため、モニターによって保護されているクリティカルセクションコードはメインメモリから共有変数を読み取る必要があります。
スピンロック
- 多くの場合、共有データのロック状態は短時間持続し、スレッドを切り替える価値はありません。
- CPUをあきらめることなく、スレッドにビジーループを実行させ、ロックが解放されるのを待つことによって
- 短所:ロックが他のスレッドによって長時間占有されていると、パフォーマンスのオーバーヘッドが大きくなります。
ロックの除去
JITコンパイル中に、実行中のコンテキストをスキャンして、競合する可能性が低いロックを削除します
锁粗化
ループ本体のロックを避けてください
同期とReentrantLockの違い
synchronized
キーワードでReentrantLock
あり、クラスですReentrantLock
デッドロックを回避するために、ロックを取得するための待機時間を設定できますReentrantLock
さまざまなロック情報を取得できますReentrantLock
複数の通知を柔軟に実装できます(Condition
)- メカニズムは異なり
synchronized
ます。オブジェクトヘッダーのマークワードが操作され、クラスのメソッドがLock
呼び出されます。Unsafe
park()
Javaメモリモデル(JMM)
Javaメモリモデル(Javaメモリモデル):それ自体は抽象的な概念であり、実際には存在せず、一連のルールと仕様を記述します。この一連の仕様を通じて、プログラム内の各変数(インスタンスフィールド、静的フィールドを含む)のアクセス方法を定義します。および配列オブジェクトを構成する要素)
揮発性
jvmによって提供される軽量の同期メカニズム
- volatileによって変更された共有変数は、常にすべてのスレッドに表示されます
- 命令の並べ替えの最適化を防ぐ
揮発性変数がすぐに表示されるのはなぜですか?
揮発性変数を書き込む場合、JMMはスレッドに対応する作業メモリー内の共有変数をメインメモリーにフラッシュします。
揮発性変数を読み取る場合、JMMはスレッドに対応する作業メモリーをメインメモリーから無効に設定します。最新の値
揮発性が再配置の最適化をどのように禁止するか
メモリバリア
- 特定の操作の実行順序を保証します
- 特定の変数のメモリの可視性を確保する
メモリバリア命令を挿入することにより、メモリバリアの前後で命令の並べ替え最適化を実行することを禁止し、さまざまなCPUのキャッシュデータを強制的にフラッシュして、CPU上のすべてのスレッドがこれらのデータの最新バージョンを読み取れるようにします。
揮発性と同期の違い
volatile
本質は、レジスタ(作業メモリ)内の現在の変数の値が不確実であり、メインメモリから読み取る必要があることをjvmに伝えるsynchronized
ことです。現在の変数をロックすることであり、現在のスレッドのみが変数にアクセスできます。および他のスレッドはブロックして待機する必要があります。volatile
変数レベルでのみ使用できます。synchronized
変数、メソッド、およびクラスレベルで使用できます。volatile
可視性のみが保証され、原子性は保証されません。synchronized
可視性と原子性の両方が保証されますvolatile
スレッドブロッキングを引き起こしません;スレッドブロッキングsynchronized
を引き起こす可能性がありますvolatile
命令の再配置を防ぐsynchronized
ことができます。変数はコンパイラによって最適化されません。の変数はコンパイラによって最適化できます。
CAS(コンペアアンドスワップ)
CASは楽観的ロックに属し、同期は悲観的ロックに属します
短所:
- サイクルタイムが長い場合、オーバーヘッドが高くなります
- 共有変数のアトミック操作のみを保証します
- ABA問題、解決策:使用
AtomicStampedReference
(内部バージョンは実際にはプラスバージョンです)
スレッドプール
ThreadPoolExecutorのコンストラクター
スレッドプール拒否戦略
新しいタスクが実行のために送信された後の判断
スレッドプールのステータス
スレッドプールサイズの選択
- コンピューターを集中的に使用し、CPUを消費します。通常、CPUコアの数+1またはCPUコアの数* 2
- IOを集中的に使用し、通常はCPUコアの数/(1-0.9)またはCPUコアの数/(1-0.8)
例:8コアプロセッサ、8 /(1-0.9)= 80ioスレッド