1.CAS ABA問題を引き起こします:
CASアルゴリズムが重要な前提条件である、この時間差はデータの変化につながる、現時点で一瞬メモリ内のデータを削除し、比較交換する必要があります。
例:スレッド1は、メモリ位置V Aから除去され、またV A、オペレーションのいくつかの値にスレッド2 B、及びスレッドのVデータはバック2 Aにオンにするから、この時間スレッド2で除去される;場合スレッド1 CAS動作がまだ成功した操作をスレッド次に、メモリAに見出されます。
CASスレッド1事業の成功にもかかわらず、しかしそれは、このプロセスが問題ではないことを意味するものではありません。
:ABAは、問題解決アトミック参照の使用+修正バージョン番号(タイムスタンプと同様に)、あなたは契約の価値の最新バージョンを入手する必要があるたびに。
2.原子参照AtomicReference
ABAの問題の例:
パッケージcom.mort.test。 輸入java.util.concurrent.TimeUnit。 輸入java.util.concurrent.atomic.AtomicReference。 パブリック クラスTestAtomicReference { 静的 AtomicReference <整数> atomicReference = 新しい AtomicReference <整数>(100 )。 パブリック 静的 ボイドメイン(文字列[]引数){ 新しいスレッド(() - > { // 执行ABA操作 atomicReference.compareAndSet(100、101 ); atomicReference.compareAndSet( 101、100 ); }、 "T1" ).start (); 新しい新しいスレッドが(() - > { // 1秒休止スレッドT2、T1が動作完了ABAを確保する 試みを{ TimeUnit.SECONDS.sleep( 1 ); } キャッチ(InterruptedExceptionあるE){ e.printStackTrace(); } システム.out.println(atomicReference.compareAndSet( 100、2019)+ "\ T" + atomicReference.get()); }、 "T2" ).start(); } }
3. ABA問題を解決:アトミックタイムスタンプの参照をAtomicStampedReference
コード例:
パッケージcom.mort.test。 輸入java.util.concurrent.TimeUnit。 輸入java.util.concurrent.atomic.AtomicReference。 輸入java.util.concurrent.atomic.AtomicStampedReference。 パブリック クラスTestABASolve { // 静的AtomicReference <整数> atomicReference =新しいAtomicReference <整数>(100)。 静的 AtomicStampedReference <整数> atomicStampedReference = 新しい AtomicStampedReference <>(100,1 )。 公共の 静的な 無効メイン(文字列[] args)を{ 新しいスレッド(() - > { int型のスタンプ=atomicStampedReference.getStamp(); System.out.printlnは(にThread.currentThread()のgetName()。 + "\トン第一版:" + スタンプ); // 1秒スレッドT1のために一時停止、T2の保証はバージョンを取得します同じ番号は、T1 試み{ (TimeUnit.SECONDS.sleep。1 ); } キャッチ{(InterruptedExceptionあるE) ; e.printStackTraceを() } // 操作ABA実行 atomicStampedReference.compareAndSet(100、101、スタンプ、スタンプ+ 1 ); スタンプ = atomicStampedReference.getStamp(); System.out.printlnは(にThread.currentThread()のgetName() + "\ T 2版:" +スタンプ); atomicStampedReference.compareAndSet( 101、100、スタンプ、スタンプ+ 1 ); // のSystem.out.println(にThread.currentThread()のgetName()+ "\ T 3版:" + atomicStampedReference.getStamp。 ()); }、 "T1" ).start(); 新しい新しいスレッド(() - > { INTスタンプ= atomicStampedReference.getStamp(); System.out.printlnは(にThread.currentThread()のgetName() +「\ Tの第1のバージョン:「+ スタンプは); // 動作完全T1のABAを確保するために、T2スレッド3秒休止 試みを{ TimeUnit.SECONDS.sleep( 3 ); } キャッチ(InterruptedExceptionある電子){ e.printStackTrace(); } ブール結果= atomicStampedReference.compareAndSet(100、2019、スタンプ、スタンプ+ 1 )。 System.out.println(。にThread.currentThread()のgetName() + "\トン执行结果:" +なる+ "\トン最新版本号:" + atomicStampedReference.getStamp()); System.out.println(。にThread.currentThread()のgetName() + "\トン当前实际最新值:" + atomicStampedReference.getReference()); }、 "T2" ).start(); } }
出力:
T1の第1バージョン:1 T2第1版: 1 、T1 2版: 2 T2実行結果:falseに 最新バージョン番号:. 3つの T2最新電流実測値: 100