Studieren Sie den zugrunde liegenden Quellcode dieser Methode
AtomicInteger verwendet CAS, muss jedoch nicht synchronisiert werden
Die Konsistenz mit der Synchronisierung ist garantiert, aber die Parallelität ist stark gesunken.
Wir verwenden CAS, um do ... zu verwenden, während wiederholte Beurteilungen vorgenommen werden, um die Konsistenz sicherzustellen und die Parallelität nicht zu verringern.
CAS ----> compare And Swap, er ist ein CPU-Parallelitätsprimitiv. Er darf während des Ausführungsprozesses nicht unterbrochen werden, was bedeutet, dass CAS eine atomare Anweisung auf der CPU ist und keine Dateninkonsistenz verursacht.
CAS-Nachteile:
1. In einer Umgebung mit hoher Parallelität sind die Kosten für den Becher extrem hoch, wenn eine while-Schleife hinzugefügt wird, um nicht erfolgreich zu beurteilen.
2. Nur die Atomizität einer gemeinsam genutzten Variablen garantieren, kann keinen Code garantieren.
3. Kann ABA-Probleme verursachen.
Vier Wörter fassen die Zibetkatze für den Prinzen zusammen.
Wenn t1 und t2 gleichzeitig mit Daten A arbeiten, ändert t1 die Daten A in B und aktualisiert sie in den Hauptspeicher, aber t2 weiß es zu diesem Zeitpunkt nicht, t1 hat B in A aktualisiert, und dann geht t2 in den Hauptspeicher Aus dem Speicher ist A immer noch in Ordnung, daher habe ich das A im Hauptspeicher in seine eigenen Daten geändert. Dies ist das ABA-Problem
Assemblersprache auf niedriger Ebene
Die Lösung für das ABA-Problem:
In der Atomklasse gibt es eine AtomicStampedReference-Klasse, die dieses Problem mit einer Versionsnummer lösen kann.
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();
}
}