このメソッドの基礎となるソースコードを研究する
AtomicIntegerはCASを使用しますが、同期する必要はありません
同期との整合性は保証されますが、並行性は大幅に低下し
ます。CASを使用してdo ... whileを使用し、一貫性を確保し、並行性を低下させないように繰り返し判断します。
CAS ---->コンペアアンドスワップ、彼はCPU同時実行プリミティブです。彼は実行プロセス中に中断されることは許可されていません。つまり、CASはCPUのアトミック命令であり、データの不整合を引き起こすことはありません。
CASのデメリット:
1。同時実行性の高い環境では、whileループを追加して判断に失敗すると、カップのコストが非常に大きくなります。
2.共有変数のアトミック性を保証するだけでは、コードの一部を保証することはできません。
3. ABA問題を引き起こす可能性があります
。4つの単語は、王子のためのジャコウネコを要約しています。
t1とt2が同時にデータAを操作する場合、t1はデータAをBに変更してメインメモリに更新しますが、t2はこの時点ではわかりません。t1はBをAに更新し、t2はメインに移動します。メモリから、Aはまだ大丈夫なので、メインメモリのAを彼自身のデータに変更しました。これはABA問題です
低水準アセンブリ言語
ABA問題の解決策:
アトミッククラスには、バージョン番号でこの問題を解決できるAtomicStampedReferenceクラスがあります。
public class ABADemo {
/**
* 这里的Integer不能大于127若大于127则不会出现ABA情况,也就是没有CAS
* true 128
* false 128
*/
private static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
private static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100,1);
public static void main(String[] args) {
System.out.println("===以下是ABA问题的产生===");
new Thread(() ->{
System.out.println(atomicReference.compareAndSet(100, 127)+"\t"+atomicReference.get());
System.out.println(atomicReference.compareAndSet(127, 100)+"\t"+atomicReference.get());
},"t1").start();
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicReference.compareAndSet(100, 2019)+"\t"+atomicReference.get());
},"t2").start();
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("===以下是ABA问题的解决===");
new Thread(() ->{
System.out.println(Thread.currentThread().getName()+"\t第一次版本号:"+atomicStampedReference.getStamp());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicStampedReference.compareAndSet(100, 127,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1)+"\t"+atomicStampedReference.getReference());
System.out.println(Thread.currentThread().getName()+"\t第二次版本号:"+atomicStampedReference.getStamp());
System.out.println(atomicStampedReference.compareAndSet(127, 100,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1)+"\t"+atomicStampedReference.getReference());
System.out.println(Thread.currentThread().getName()+"\t第三次版本号:"+atomicStampedReference.getStamp());
},"t3").start();
new Thread(() -> {
int stamp = atomicStampedReference.getStamp();
System.out.println(Thread.currentThread().getName()+"\t第一次版本号:"+atomicStampedReference.getStamp());
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicStampedReference.compareAndSet(100, 2019,stamp,stamp+1)+"\t"+atomicStampedReference.getReference());
System.out.println(Thread.currentThread().getName()+"\t最新的版本号:"+atomicStampedReference.getStamp());
},"t4").start();
}
}