まず、マルチスレッド三つの特徴
1.アトミック:すなわち、1つまたは複数の操作またはすべての操作を行うと、プロセスは、任意の因子の中断実行されず、またはそれが実行されません。
古典的な例は、銀行口座振替の問題である:
マイナス口座への口座A、Bから千元プラス千元:例えば、口座B千元に口座Aからの転送は、それは2つの操作を含める必要があります。これらの2つの操作が、いくつかの予期しない問題があることを保証するために、原子性を持っている必要があります。
我々私+ 1 =なども真オペレーショナルデータ、; Iが算出されるIの読み出し値、を含む、書かれた私。でこのコード行Javaがアトミック利用できない、そこ我々はまた、使用の同期に必要なので、問題は、マルチスレッド実行されていることと、この機能することを確認するために、これらの事をロックします。
実際には、アトミックは、データの一貫性、セキュリティネジ部を確保することです、
2.可視性:複数のスレッドが同じ変数にアクセスすると、スレッドはこの変数の値を変更し、他のスレッドが直ちに変更された値を見ることができます。異なるCPU、その後、1スレッドで2つのスレッドがメインメモリをリフレッシュするためにスレッドを変更しなかったiの値を変更した場合表示されませんでした変数の1、、それはiの値を肯定する前に、まだある、スレッドを2スレッドと私は使用これは問題の可視性です。
3.発注:注文コードで実行されるプログラムの実行シーケンス。プロセス効率を向上させるために一般的なプロセッサでは、コードの最適化を入力するかもしれない、それはコードの順序と一致するために、個々の文でプログラムの実行を保証するものではないが、それは、最終的なプログラムの実行及びコードシーケンスの結果ことを保証します結果は同じです。次のとおりです。
= 10 int型; //ステートメントを1
int型のR = 2; //声明2
A = A + 3; //声明3
rは* =; //ステートメントを4
並べ替えので、彼は実行の順序可能性があること2-1-3-4,1-3-2-4である
ことは、依存関係を壊すためではなく、おそらく2-1-4-3。
我々は、マルチスレッドプログラミングの時にこの問題を検討する必要があるので、明らかに再発注単一のスレッドは、すべての問題を持っているつもりが、必ずしもではないマルチスレッドされていません。
二、Javaのメモリモデル
1.共有メモリモデルは、Javaメモリモデル(JMMをいう。)を意味し、JMMは、共有変数、1つのスレッドを記述することを決定し、それが別のスレッドで見ることができます。メインメモリ(主記憶装置)、各スレッドがプライベートローカルメモリ(ローカルメモリ)を有し、スレッド変数ストレージ間で共有:ビューの抽象的な点から、JMMはスレッドとメインメモリとの間の抽象関係を定義します、読み取り/書き込みにスレッドのコピーを保存されたローカル・メモリは、変数を共有しました。JMMローカルメモリは抽象的な概念であり、本物ではないです。これは、キャッシュ、書き込みバッファ、レジスタとその他のハードウェアおよびコンパイラの最適化をカバーしています。
2.ピクチャー
マップビューからは、スレッドAとBの間のスレッドが伝達されるように、それは以下の2つのステップを経る必要があります:
2.1。まず、更新されたスレッドAのローカルメモリAは、メインメモリにフラッシュされる変数を共有しました。
2.2。次に、スレッドBは、Aが共有変数を更新したスレッドの前にメインメモリに読み込みます。
3.これらの2つのステップは概略して説明します。
上に示した3.1。ように、A及びBは、共有変数xのメインメモリコピーでローカル・メモリを有します。初期仮定すると、これら3つのメモリのxの値は0です。一時A.で自身のローカルメモリに格納されたスレッドは、実行されると、(1の値を仮定して)は、xの値を更新します スレッドAおよびスレッドBが通信を必要とするとき、XのスレッドA最初の値は、ローカルメモリ変更後、メインメモリにフラッシュ所有し、このときのxの値は、メインメモリは1となります。その後、スレッドBのローカルメモリも1になるこの時点で、更新スレッドAの後にxの値をxの値を読み取るためにメインメモリにスレッドB。
全体として、実質的にスレッドAスレッドでこれらの2つのステップはBにメッセージを送信し、通信処理をメインメモリを介して行かなければなりません。メモリ保証Javaプログラマの可視性を提供するために、メインメモリと、各スレッドのローカルメモリ間の相互作用を制御することにより、JMM。
4.まとめ
何ですかJ AVAのメモリ・モデルは:のJava メモリモデルはと呼ばJMM 、セットが定義スレッドに別の可視スレッド。共有メインメモリに格納された変数は、各スレッドは、独自の持っているローカルメモリを通りスレッドが発生しますので、複数のスレッドがタイムリーにメインメモリにローカルメモリをリフレッシュしていない可能性のあるデータにアクセスする際のセキュリティ問題を。
揮発性のあるものを第三に、
換言すれば、1の値の後、修正変数が揮発性であるスレッドの修正の可視性と、それが変更された値がすぐに他のスレッドは、あなたが修正すぐに入手することができます読み取る必要がある場合には、メインメモリに更新されていることを確認します。
2.のJavaプログラムの効率をスピードアップするために、変数のいくつかの動作は、通常はメインメモリに同期した後、スレッドレジスタまたはCPUキャッシュ上で実行され、揮発性改質剤は可変で追加されていますこれは、直接読み込み、メインメモリの書き込みです。
3.Volatileは、スレッド間で共有変数のタイムリーな視認性を確保ますが、保証アトミックできません。
class ThreadVolatileDemo extends Thread {
public volatile boolean flag = true;
@Override
public void run() {
System.out.println("开始执行子线程....");
while (flag) {
}
System.out.println("线程停止");
}
public void setRuning(boolean flag) {
this.flag = flag;
}
}
public class ThreadVolatile {
public static void main(String[] args) throws InterruptedException {
ThreadVolatileDemo threadVolatileDemo = new ThreadVolatileDemo();
threadVolatileDemo.start();
Thread.sleep(3000);
threadVolatileDemo.setRuning(false);
System.out.println("flag 已经设置成false");
Thread.sleep(1000);
System.out.println(threadVolatileDemo.flag);
}
}
4.結果
4.1。結果(プラス揮発性)
开始执行子线程....
flag 已经设置成false
线程停止
false开始执行子线程....
flag 已经设置成false
线程停止
false
4.2結果(揮発せず、結果もセットfasleされた理由?。それを実行する理由:スレッド間のコピーを読んで、表示されていない、使用するメインメモリへの溶液の結果を読み取るための時間がありません。 volatileキーワードは、スレッド間の可視性を解決する際に、各スレッドは、すべての「メインメモリ」値の値を読むことを余儀なくされました)
开始执行子线程....
flag 已经设置成false
false
四、揮発性と同期の違い
1.私たちはものの、原子揮発有するが、可視性を保証するものではないことを見ることができます。
2.パフォーマンス、コードの一部を実行するための複数のスレッドを防ぐために、synchronizedキーワードは、それはプログラムの実行の効率化、およびいくつかのケースではvolatileキーワード同期よりも優れたパフォーマンスに影響を及ぼします。
3.しかし、揮発性のキーワードはアトミック操作を保証することはできませんので、揮発性のキーワードは、synchronizedキーワードに代わるものではありません注意してください。
第五に、の終わり
1.alwaysは、信仰を守ります!