揮発性(正確な作成)

(1)読書指導

   1.この記事はデザイナーの役割を考えています。

   2.それが何であるか、そしてそれがなぜであるかを理解します。

   3.完璧なものはありません。アプリケーションのシナリオに従ってください。

   上記の3つの点について、多くのスペースを使ってそれについて話すことを許してください!

(2)開発履歴(設計者の視点)


注:次の述語「I」は、Javaデザイナーのみを表しています(ただし、正しく理解されていません)。

   1. Java 1.5をリリースする前は、当時のビジネスシナリオはシングルコア市場でしたが、Javaがそれほど大きくなるとは予想していませんでした。当時は、いわゆる並行プログラミングを検討し、プリミティブレベルの命令()を使用しましたが、他のスレッドは、同期コードブロックと呼ばれているため、現時点ではブロックされます。これを達成するためにsynochrizedキーワードを使用します。もちろん、Java初級レベルはメソッドまたはオブジェクトをロックできることを理解しています。javacを編集すると、同期コードブロックの前後にmonitorenterおよびmonitorexitバイトコード命令が生成されます。参照型パラメーターがロックされたオブジェクトを示している場合、このオブジェクト参考として。もちろん、参照が空の場合は、変更された(インスタンスまたはクラス)メソッドを検討できます。


   2.私たちのチームが導いた主要な変更は、C#との競争です。1.XバージョンをXバージョンに変更することを決定しました。占い師は、この名前を転送するために必要であると言っていました(冗談です)。まず、Javaを使用するプログラマーは多くの欠点を提起しました。Javaをより完全にするために、それを聞いてみましょう。マルチスレッド化された高い並行性の下でマルチコア時代に適応します。ユーザーは、複数のアプリケーションシナリオでSynochrizedを使用することは少し重たいと感じます。たとえば、共有変数の場合、書き込むよりもはるかに多くを読み取ります。スレッドをブロックせずにそれを行うことができます。ブロックしているスレッドのシノクロイズは重すぎます。それを置き換える必要があり、一部のアプリケーションシナリオでは、その利点を実現できます。


   3. 揮発性はSynochrizedの利点を拡張します。可視性、原子性、順序など、Synochrizedの利点を継承する必要があります。synochrizedは同期されたコードブロックであるため、スレッドがこのリソースを操作している場合、このリソースを必要とする他のスレッドは中断されます。そのロックで操作できるスレッドは1つだけです。スレッド間のシリアル実行では、最初のスレッドの問題は発生しませんが、これに続いて、ロック、ロックの解放、コンテキストの切り替え、スケジューリングの遅延などがすべて、同期化されたより重い原因です。それ以来、より軽量なロックを設計できますか?書き込みよりも読み取りが多いなど、楽観的な状況では、この大きな人を別のものに置き換えることができます。


   4.設計を行います。この変数に重いロックは必要ないため、この変数は変更されると感じますが、ロックは使用しないことをjvmに通知します。注意してください。この変数をvolatile(volatile)に変更します)、この変数は現時点ではVIPです。あなたは私がVIPだと言っています。通常の変数はどのように私のVIPステータスを反映しますか?さて、すべての一般ユーザーが保存することを伝えます。マルチコアシステムでは、各CPUにキャッシュがありますが、メインメモリにはキャッシュがあります。キャッシュコヒーレンシを解決するには、キャッシュとメインメモリの整合性を確保する必要があります。Javaメモリ領域にリンクする必要がある場合、スタックはワーキングメモリであり、ヒープはメインメモリです。


   5.通常のユーザーはその正確さを気にしません。変数を取得する場合、変数は(ヒープとして理解できる)メインメモリに直接コピーされ(Javaメモリモデルでは、すべての変数がメインメモリに格納されることが規定されています)、変数を独自の作業メモリにコピーします。 (プライベート、スタックとして理解できます)、すべての操作(読み取り、割り当て)はワーキングメモリで実行されます。変数がメインメモリからワーキングメモリにコピーされる方法、およびワーキングメモリからメインメモリに同期する方法を説明するために、8つのアトミック操作があると規定しています。8つの操作は4に簡略化されており、8種類のスポイラーは(ロック、ロック解除、読み取り、ロード、使用、割り当て、保存、書き込み)は、これらの4種類(読み取り、書き込み、ロック、ロック解除)として理解されます。

(C)揮発性の達成を原子性、可視性、整然としたものとして設計する


注:2つの可変スロットを占有するdoubleおよびlongは一時的に無視されます(確率は非常に小さいです)


   1.原子性とは何ですか?Javaコードの行を記述するとき、それは不可分ですか?i ++はもちろん、最下部のアセンブリに4つの演算があります。つまり、iの値を取り、定数1を取り、i + 1演算を行い、i + 1をiにコピーします。合計4つです。もちろん、バイトコード命令を意図したものではありません。アトミック操作、バイトコード命令インタープリターは、そのセマンティクスを実現するためにコードの多くの行を実行します。今回、メインメモリからワーキングメモリに変数をコピーするとき、原子性の表面的な理解は正しいです。もちろん、iの値がアトミックであることのみを保証できます。(原子故障)


   2.可視性を実現しましょう。2.5で一般ユーザーによる共有変数の読み取りについて説明しました。揮発性の変更された変数の目的は、この変数がすべてのスレッドから見えるようにすることです。つまり、1つのスレッドがこの変数の値を変更します。すぐに知る価値があります。ここでは、2つの前提を宣言します。一方の結果は現在の変数の値に依存しないこと、または単一のスレッドのみが変数の値を変更することを保証できます(i ++)。もう一方の手の変数他の状態変数と共有する必要はありません。一定の制約参加しているので、あまり深く理解していません。誤解を避けるために、この参照コードを投稿しました(「Java仮想マシンの第3版の詳細な理解」コードリスト12-3からの抜粋)

// 被volatile修饰的布尔类型,用来做控制逻辑代码
volatile boolean shutdownRequested;
public void shutdown(){
	shutdownRequested = true;
}

public void doWork(){
	while(!shutdownRequested){
		
		// 执行逻辑代码 
	
	}
}

   3.これを達成できます。つまり、コードを最適化しないと仮定すると、この変数は不安定な要素であると考え、この変数を作業メモリに長期間保存せず、使用前と使用後にロードする必要があります。毎回使用する値がメインメモリ内で最新であることを確認できるように、それを使用する必要がありますが、可視性を確保する方法は?変更された値を他の人にすばやく見せるにはどうすればよいですか?各ストアがライターになった後、ライターを保存する必要があるたびに、操作の直後に変数がメモリに確実にリフレッシュされるようにすることを規定していますただし、volatileで変更された変数は同時実行では安全ではないため、ハードウェアの観点からは最新の値のみが取得され、操作が安全である保証はありません。


   4.並べ替えの問題を解決します。まず、なぜ再注文するのか理解していますか?作成するコードはバイトコードにコンパイルされ、バイトコードはマシンコードになるとおおまかに考えることができます。次に、並べ替えの最適化はマシンレベルの最適化です。事前に実行されるのは、このステートメントに対応するアセンブリコードが事前に実行されることです。 Javaコードの行は、多数のアセンブリコードに解析する必要があります。まず、Synochrizedは共有変数を1つのロックでのみロックできるようにすることでシリアル化を保証し、スレッドの前のセキュリティを確保することを学びました。jdk1.5に変更を加え、二重ロック検出を備えたシングルトンを実装できるようにしました。


   5. 揮発性の変更された変数の代入後に、追加の「lock addl $ 0x0、(%esp)」操作を実行します。理解していなくても問題ありません私も理解していません。この操作は、メモリバリアに相当します(ガベージコレクターのメモリバリアではありません)。この命令☞並べ替え中に次の命令をメモリバリアの前の位置に並べ替えることはできません。このバイトコード命令は明らかにプラス0の操作です。 IA32マニュアルではロックプレフィックスをnopで使用することは許可されていないため、nop(操作なし)を使用しないのはなぜですか。ロックプレフィックスの役割は、このプロセッサのキャッシュをメモリに書き込むことです。これにより、他のCPUによって保存されたローカル変数が無効になる可能性があります。つまり、他のローカル変数は、無効になったときにメインメモリからのみ読み取ることができ、メモリの可視性も保証されます同時に、変数の値を変更する場合は、変数が正しく取得され割り当てられていることを確認します。これは順序を確実にするためです。

総括する


1.可視性は、ロードと使用、割り当て、保存に関連しています

2.割り当ては、割り当ての前後の順序を確実にするために、これに基づいて行われます。

リファレンスブック:「Java Virtual Machine Third Editionの詳細な理解」
リファレンスウェブサイト:volatile Baidu Baike


付録:揮発性実装i ++



間違いを指摘してください、私はとても感謝しています!

おすすめ

転載: blog.csdn.net/qq_44112474/article/details/108206090