図1に示すように、ツールの導入(てjavap)
1、てjavap、主にJavaコンパイラのメカニズムに助け開発者の洞察に使用、主なオプションは次のとおりです。
- -c分解法コード、すなわち各バイトコードを表示する具体的な方法
- -public |保護|パッケージ|プライベートディスプレイは、クラスメンバーのレベルの種類を指定するために使用されます
- -verbose詳細情報を表示し、さらに
入力:てjavap -c Test.class
D:\my-workspace\mayun\JUCDemo\out\production\JUCDemo\com\pingan>javap -c Test.class
Compiled from "Test.java"
public class com.pingan.Test {
static volatile java.lang.String b;
public com.pingan.Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: getstatic #3 // Field b:Ljava/lang/String;
6: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
9: return
static {};
Code:
0: ldc #5 // String hello
2: putstatic #3 // Field b:Ljava/lang/String;
5: return
2、揮発性
コマンドキーは命令があるため、コンパイラの最適化を省略することがないようにするために、揮発性であるようvoliate・タイプ修飾子が役割です。
2.1揮発性特性
- 可視性を達成する:動作変数の異なるスレッドの視認性を確保するため、つまりスレッドは変数の値を変更し、他のスレッドにこの新しい値が直ちに表示されています。
- 整然とした:命令並べ替えの禁止。
- 原子性:揮発性私は++この操作の原子が保証できない、唯一の単一の原子動作を保証するため、
2.2揮発性の実装の原則を - 可視性揮発性メモリ変数はメモリバリア(メモリバリア)の実装です。
メモリバリアとして知られている障壁から、CPUの命令です。
プログラムは、メモリバリアの特定のタイプを挿入することにより、コンパイラの特定のタイプを禁止する、異なるコンパイラとCPUで同一の結果を確実にするJMM順序、プロセッサの実行性能とコンパイラ並び替え命令を向上させるために、実行されます何があっ指示することができず、このメモリバリア命令の並べ替え:発注と落胆プロセッサを並べ替え、メモリバリアを挿入するには、コンパイラとCPUを教えてくれます。
2.3揮発性のアプリケーションシナリオ
1は、使用条件は、揮発性を持っている必要があります
- 書き込み操作は、可変電流値に依存しません。
- 式では他の変数との不変変数に含まれていません。
図2に示すように、状態は、プログラム内の他のコンテンツの真に独立している場合にのみ揮発性を使用するためです。
モード1:ステータスフラグが
初期化またはシャットダウン要求:知識のような、イベントが発生した重要な一回限りですので、ちょうどブールフラグを使用達成するために揮発性の変数の使用を規制します
volatile boolean shutdownRequested;
......
public void shutdown() { shutdownRequested = true; }
public void doWork() {
while (!shutdownRequested) {
// do stuff
}
}
モード2:使い捨て安全性がリリース
同期の欠如は、代わりに元の値のオブジェクト参照を記述するかを決定せ、視認性を達成しないようにつながることができ、同期が存在しない場合に、より困難になる、あなたは、オブジェクト参照が発生する可能性があります(別のスレッドによって書き込まれた)更新された値とオブジェクトが存在の状態の古い値。
public class BackgroundFloobleLoader {
public volatile Flooble theFlooble;
public void initInBackground() {
// do lots of stuff
theFlooble = new Flooble(); // this is the only write to theFlooble
}
}
public class SomeOtherClass {
public void doWork() {
while (true) {
// do some stuff...
// use the Flooble, but only if it is ready
if (floobleLoader.theFlooble != null)
doSomething(floobleLoader.theFlooble);
}
}
}
モード3:独立した観察者は、
単に揮発性の安全な使用の他のモードでは、定期的に内部使用のための観測を公開しています。例:後にいつでも見ることができるので、バックグラウンドスレッドが数秒ごとに一度読んセンサー、および揮発性変数は、現在のドキュメントが含まれている更新かもしれないが、その後、他のスレッドが変数を読み取ることができ、周囲温度環境を感知するセンサーがあると最新の温度値。
public class UserManager {
public volatile String lastUser;
public boolean authenticate(String user, String password) {
boolean valid = passwordIsValid(user, password);
if (valid) {
User u = new User();
activeUsers.add(u);
lastUser = user;
}
return valid;
}
}
モデル5:安価な読み取り - 書き込みロックの戦略
- インナーは++ Xは、実際には3つの操作(読み取り、追加、ストア)単純な組み合わせであることを、カウンタの機能を実現するための揮発性は十分。インクリメンタル揮発カウンタ動作を実行しようとしているときに複数の行が起こった場合、価値が失われる可能性が更新されます。
- あなたが書き込み操作よりもはるかに読めば、あなたは内部ロックを使用することができ、かつ揮発性の変数は、共通のコードパスの組み合わせのオーバーヘッドを削減します。
- カウンタのインクリメント動作の安全な使用を確実にするために同期原子であり、現在の結果の視認性を確保するために、揮発性の使用。まれ場合は、更新の単語ならば、方法は、パフォーマンスを向上させるために変更することができます。読み取りパスのオーバーヘッドのが唯一の揮発含むので、通常より良い非競合ロック取得のコストよりもある、読み込みます。
@ThreadSafe
public class CheesyCounter {
// Employs the cheap read-write lock trick
// All mutative operations MUST be done with the 'this' lock held
@GuardedBy("this") private volatile int value;
public int getValue() { return value; }
public synchronized int increment() {
return value++;
}
}
モデル6:ダブルチェック
多くの人が多分、キーワードので、プログラムも非常に良い実行することができませんが、コードの安定性は常に100%ではない、揮発性のキーワードを無視しますので、実施形態の単一のケースを当時、嵐に対処するための隠されたバグ。
class Singleton {
private volatile static Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
syschronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
推奨遅延ロードエレガントなライティング:
public class Singleton {
private static class SingletonHolder{
static Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}