これらのここのAtomicIntegerの例と、同様の達成などのAtomicInteger、AtomicLongとして、非ブロッキングスレッドセーフの包装を、提供するために、スタートからのJava 1.5。
危険な動作が導入スタンプ関連のハードウェアレベルのアトミック操作提供JDK内で使用されるユーティリティクラスであるのAtomicIntegerクラス基づいてhttps://www.jianshu.com/p/2e5b92d0962eを。JDK1.8から、次のコード。
メンバ変数を初めて目:
1 プライベート 静的 最終的な安全でない危険= Unsafe.getUnsafe(); 2 // メモリオフセットの値 3。 プライベート 静的 最終 ロングvalueOffset; 4 5。 静的{ 6。 試し{ 7。 // オフセット値メモリを取得 8。 valueOffsetは= 危険を.objectFieldOffset 。9 (のAtomicIntegerのクラス .getDeclaredField( "値" )); 10 } キャッチ(例外EX){ スロー 新しい新しいエラー(EX);} 。11 } 12 // 值 13 プライベート 揮発性 のint値。
値が特定の値、重要性と価値の可変度があれば、これらの二つの変数の役割を理解するように、のAtomicIntegerは、基本的に理解し、変数に相当するメモリの視認性を確保するための揮発性の変数であり、他のvalueOffsetあります、そしてなぜこの特定の変数、紹介している関連メソッドを参照してください。
安全でない、関連メソッドの役割に基づいてメソッドのAtomicIntegerクラスはすべて、valueOffsetの役割と価値を説明するための唯一のいくつかの方法ここでは、自分自身やGoogleの最初に与えられたリンクをチェックしてください。
1 公共 最終 int型のget(){ 2 戻り値; 3 } 4 5 パブリック 最終 ボイド集合(INT newValueに){ 6 値= newValueに。 7 }
これは、設定した値を取得するための基本的な二つの方法です。値が揮発性の変数であるが、このセット()メソッドはテストであることが、安全になることはないが、ことに留意すべきです。
1 パブリック クラス AtomicIntegerExampleは実装のRunnable { 2 プライベート 静的のAtomicIntegerのAtomicInteger = 新規のAtomicIntegerを(); 3 プライベート 静的 CyclicBarrierをバリア= 新しい CyclicBarrierを(2 )。 4 プライベート整数。 5 6 プライベートAtomicIntegerExample(整数A){ 7 この .A = 。 8 } 9 10 パブリック 静的 ボイドメイン(文字列[]引数){ 11 AtomicIntegerExample例1 = 新しい AtomicIntegerExample(1 )。 12 AtomicIntegerExample例2 = 新しい AtomicIntegerExample(2 )。 13 INT B = 0 。 14 int型のカウント= 0 ; 15 ながら(<10カウント{) 16 スレッドスレッド1 = 新しいスレッド(例1)を、 17 スレッドのスレッド2 = 新しいスレッド(例2)。 18 thread1.start()。 19 thread2.start()。 20 トライ{ 21 thread1.join(); 22 thread2.join()。 23 } キャッチ(InterruptedExceptionある電子){ 24 e.printStackTrace(); 25 } 26 であれば(B =!atomicInteger.get()){ 27 System.out.print(のAtomicInteger +」 " )。 28 B = atomicInteger.get()。 29 数++ ; 30 } 31 barrier.reset()。 32 } 33 } 34 35 @Override 36 公共 ボイドラン(){ 37 のtry { 38 barrier.await()。 39 } キャッチ(InterruptedExceptionある電子){ 40 e.printStackTrace(); 41 } キャッチ(BrokenBarrierException電子){ 42 e.printStackTrace(); 43 } 44 // 线程不安全 45 atomicInteger.set(A)。 46 } 47 }
出力は2121212121です。
いくつかのケースでは、まだ次の場合には原子性を確保するために揮発性の変数を使用してロックを解除することができ、原子性を確保するためにロックする必要があるのでによる揮発性変数の可視性にのみ、保証:
1)演算結果は、変数の現在の値に依存しない、または単一のスレッドが変数の値を更新することができることを確実にします。
2)変数は、他の状態変数一定の制約に参加する必要はありません
ここでの方法、満足しているが最初の点を設定し、それに加えてnewsValue値が第2の点が満たされていない、式であり、具体的には、私の以前のブログをチェックするJava JVMのメモリ・モデルの理解を。getおよびsetメソッドに加えて、すべてのメソッドはすべて、その理由をvalueOffsetを使用し、私は揮発性メモリの並べ替えを最適化するために、関連するJVMを禁止しているためと理解しています。それでは、他の方法を見てみましょう:
1 公共 最終 INT getAndSet(INT newValueに){ 2 リターン unsafe.getAndSetInt(この、valueOffset、newValueに)。 3 }
この方法は、現在の値を取得し、newValueにに値を設定し、安全でない方法を探すことです。
1 公共 最終 INT getAndSetInt(オブジェクトVAR1、ロング VAR2、int型VAR4){ 2 のint VAR5を、 3 行う{ 4。 VAR5 = この .getIntVolatile(VAR1、VAR2); // アドレス原子アドレスとオフセットVAR1 VAR2を得るために変数の値は 5。 } しばらくは(!この .compareAndSwapInt(VAR1、VAR2、VAR5、VAR4)); // スピンCAS操作が正常にVAR4に値をtrueに戻します 6。 7。 リターン VAR5は、// 古い値を返す 8 }
これは、上記の方法から分かるように安全でない楽観的ロックが使用され、実際に、楽観的ロック機構を使用します。
lazySet差設定方法及び包装方法は、視認性を確保するために、揮発性変数セット割り当てを使用して、原子の最も課題であるが、lazySetを使用して、(これは添加揮発書き込みバリアとストア負荷禁止並び替えに)いくつかのパフォーマンスを失うことになります安全でない方法がputOrderedIntクラスであり、それのJDK公式の説明は、その視認性を保証することができないので、、、putOrderedIntの並べ替え方法の次の命令が存在することになるが、メモリバリアputOrderedIntは、揮発性メモリバリアの比を用いて、(ストアのストア)を使用し(ストア負荷)より良い性能は、そうlazySet方法は、性能が、可視性を失うことを確認することです。
要約すると、格納された値の特定の値は、主な役割は、使用の視認性を確保することである、とvalueOffsetメモリオフセット値が格納されているのAtomicInteger危険ベースの実装のクラス、安全でないクラスの使用主な役割で使用される変数は、性能を保証することです。