マルチスレッドの基礎(a)は - Javaのメモリモデル

  より良いJavaの内部モデルを理解するために、我々は、単にCPUのキャッシュモデルをリコールする必要があります。

CPUキャッシュキャッシュ

  コンピュータでは、CPUの計算速度は速く計算するが、しかし、コンピュータの作業の大半は完了するためにCPUに依存することはできません。また、あなたは、メモリ素子の計算結果等を、内層とのデータの相互作用を含め、読み書きする必要があります。しかしながら、コンピュータ記憶装置およびCPUの動作速度のギャップは数桁を有する、現代のコンピュータは、通常、リードの間に層を追加して、動作のために可能な限り近いとCPU処理速度CPUのキャッシュのようなメモリデバイスの速度を書きますその操作は、メインメモリにキャッシュからフラッシュ操作の終了後に迅速に行うことができるので、キャッシュに必要なデータをコピーし、その読み遅いCPUを待つと内層を記述する必要はありません。

  矛盾のプロセッサ速度とメモリへの良い解決策のストレージキャッシュの相互作用が、それはまた、新たな矛盾紹介:メモリ整合性の問題を。複数のプロセッサ・コンピューティングタスクを配置し、メインメモリ領域の同じ部分されている場合は、この問題を解決するために、プロセッサはキャッシュをアクセスするたびにデータの一貫性を維持するためにいくつかのルールに従う必要があります、メモリの整合性の問題につながります。これらのルールは、コヒーレンシプロトコルをキャッシュするために専門家の名前が付けられています。最も有名なの一つは、インテルMESIプロトコルです。MESIプロトコルは、各共有変数は、一貫性のあるキャッシュコピーに使用されることを確実にします。一般的な考え方は次のとおりです。キャッシュにCPUの動作データの間に、変数が共有変数であることが判明した場合、変数のコピーが他のキャッシュに存在していることを意味し、その後、彼らは、次の操作を行います。

    1)読み出し動作、任意の処理を行うことなく、直接、CPUレジスタにキャッシュ内のデータを読み取ることができます。

    2)書き込み動作、他のキャッシュの信号は、この変数のコピーは、変数が読み取られる場合に、確保されているメインメモリに新たな値を読み取る必要があります。

  コード実行の論理的順序でコードで計算結果の全体的な結果であることを確保しつつ、内部ユニットを算出するためのプロセッサが完全に可能な限り利用することができ、キャッシュを増加させることに加えて、プロセッサは、最適化された注文の実行コードを入力するかもしれません一貫性のあります。注文執行と同様のCPUの最適化のうち、Java仮想マシンタイムコンパイラは同様の命令並べ替え(命令の並べ替え)最適化されています。

Javaのメモリモデル

  Javaのメモリモデル(Javaのメモリモデル、JMM)は、コンピュータのメインメモリで動作するJava仮想マシンの相互作用の詳細を定義します。すなわち、変数JVMに格納され、メモリ内のそのような可変メモリの低レベルの詳細から除去されます。ここで、変数は、インスタンス・フィールド、静的フィールドとオブジェクトの配列、即ち、データを共有することができるが含まれます。彼らは民間のスレッドであり、共有されることはありませんので、何の競争が存在しないがあるだろう、ローカル変数やメソッドの引数は含まれません。次のようにJMMは、スレッドとメインメモリとの間の抽象関係を定義します。

  1)変数が格納され、メインメモリの共有、各スレッドがアクセスすることができ、メインCPUキャッシュメモリは、メインメモリのモデルを比較することができる場合、ここでは、仮想マシンのメモリの一部だけです。

  2)各スレッドはローカルメモリ、CPUのキャッシュモデルはキャッシュで比較することが可能と呼ばれる、独自のプライベートメモリを持っています。

  3)ワーキングメモリは、そのスレッド共有変数のコピーを保存することができます。

  4)メインメモリに直接変数を操作することができない、ワークメモリで実行される(書き込み、読み出し)変数に対するすべての操作をスレッド。

  5)異なるスレッド間で直接他の変数のワーキングメモリにアクセスすることができない、スレッド間で渡される変数の値は、メインメモリを完了するために必要とされています。

  Javaのメモリモデルが基礎valatileキーワードを築くために、私たちの将来のマルチスレッド化のために学ぶことができる学習します。

 

  並行プログラミングでは、3つの必須特性、すなわちアトミック、秩序と可視性があります。私たちは、JMMにこれら三つの特性を確保する方法を見て。

JMMと不可分

  原子性は、すべてのステップが一回の操作に含まれていることを意味し、いずれかのすべてが実行されたり、完全な実行されません。この概念は、物事のリレーショナルデータベースの一貫性で比較することができます。

Javaでは、基本データ型、参照型の変数を読み取る、割り当てがアトミックです。しかし、いくつかの操作が一緒に原子組成であり、それは必ずしも原子ではありません。たとえば、次のような共通のインクリメント演算子: 

そして++

  この文は、実際には3つの操作の組み合わせから構成されています。

  1)スレッドがメインメモリ、現在のスレッドの作業メモリ内に格納されているコピーからyの値を直接取得されたスレッドの実行中にワーキングメモリに既にコピー、IF(y)を読み出し、実行します。

  Y 2)実行スレッドプラス動作を行います。

  3)リフレッシュメインメモリへのyの値。

  JMMは、基本的な読書と原子の割り当てを保証し、他ではあなたには、いくつかのコードの原子を取得したい場合、あなたは後で学びますsynchronizedキーワードを使用するか、またはJUCロックにすることができ、保証するものではありませ。

 

JMMと可視性

  可視性は共有変数のためのプログラムが変更さを意味し、他のスレッドはすぐにこの変更を知ることができます。変数の値に新しい変数の前に戻ってメインメモリに新たな同期後変数の値を変更することにより、JMMは視認性を達成するために、メインメモリ依存的伝達媒体としてブラシメインメモリから読み出されます。Javaは秩序を確保するための多くの方法が用意されています。

  1)、メインメモリに直接(もちろん、ワーキングメモリにフラッシュされる)になり、書き込み動作のための共有リソースは最初のワーキングメモリを変更する共有リソースへの読み出し動作、変数は揮発性修飾された揮発性のキーワードを使用し値は、その後すぐにメインメモリにフラッシュされます。

  2)同期キーワードの使用、同期キーワードだけつのスレッドが同時にロックを取得することを確認し、その後、同期方法を実行するためには、動作する変数を共有しました。そして、ロックが解除される前に、メインメモリにフラッシュ変数を変更することであろうことを保証します。

  3)明示的なロックロックを使用してJUCは、役割とsynchronizedキーワードに似てますが、より軽量synchronizedキーワード、と比較します。

 

JMMと順序

  JMMでは、注文執行と命令並べ替え、最適化の最適化のうち、CPUのキャッシュにコンパイラとCPUの命令並べ替え、すなわち応力を可能にします。シングルスレッドの場合は、何でもあなたはマルチスレッドのために、命令の並べ替えは、エラーが発生することがありますどのように、問題はないが、最適化したいです。JMMは、同期のいずれかの表示なしに、いくつかの自然順序付け規則を持っています(実際には、私は基本的な同期が使用されていることと信じて)の順序で物事を保つことができることを意味し、このルールは、以下のような事前発生の原則であり、

  手続きのルールを起動します。トレッドは前のスレッドのいずれかのアクションにメソッドを起動し、スレッドが唯一の真の開始後に実行することができ、それ以外の場合は単なるオブジェクトです。

  ルールの端部は、オブジェクト:最初のオブジェクトの初期化の完了はfanalize法の前に発生します。

  ブロッキングルール:最初のロック解除操作はロックとロックの操作で発生します。

  传递规则:Happens-before 原则具有传递性。

如果一个操作无法从 Happens-before 原则推导出来,那么就无法保证有序性。

  与保证可见性一样,也可以使用 volatile 关键字、synchronized 关键字、JUC 提供的显式锁lock来保证有序性。其中 synchronized 保证有序性是利用“同一时间只有一个线程获得锁,然后执行同步方法,对共享变量进行操作”的这一特点来保证有序性;而 volatile 则直接暴力的禁止编译器和 CPU 的任何指令重排序,因此保证了有序性。

 

  在了解了 JMM 模型之后可以更方便学习多线程知识,特别是在后面学习 volatile 关键字的时候就会显得得心应手。

 

おすすめ

転載: www.cnblogs.com/dogeLife/p/11391863.html