GetAndIncrement von AtomicInteger entspricht i ++. Warum kann Atomizität garantiert werden?

Studieren Sie den zugrunde liegenden Quellcode dieser Methode
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein

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
Fügen Sie hier eine Bildbeschreibung ein

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();


    }
}

Ich denke du magst

Origin blog.csdn.net/qq_36905956/article/details/105857254
Empfohlen
Rangfolge