Tiefes Verständnis von CAS und atomaren Referenzen

Tiefes Verständnis von CAS und atomaren Referenzen

Ein tiefgreifendes Verständnis von CAS

Was ist CAS?

ublic class CASDemo {
    
    

    //CAS compareAndSet:比较并交换
    public static void main(String[] args) {
    
    
        AtomicInteger atomicInteger = new AtomicInteger(2020);

        // 期望、更新
        // public final boolean compareAndSet(int expect, int update)
        // 如果我期望的值达到了,那么就更新,否则,就不更新, CAS 是CPU的并发原语!
        // ============== 捣乱的线程 ==================
        System.out.println(atomicInteger.compareAndSet(2020,2021));
        System.out.println(atomicInteger.get());
        //atomicInteger.getAndIncrement();

        System.out.println(atomicInteger.compareAndSet(2021,2020));
        System.out.println(atomicInteger.get());
        // ============== 期望的线程 ==================
        System.out.println(atomicInteger.compareAndSet(2020,6666));
        System.out.println(atomicInteger.get());


    }
}

unsichere Klasse

Fügen Sie hier eine Bildbeschreibung ein

Wortoperationsspeicher hinter der obigen Abbildung

Fügen Sie hier eine Bildbeschreibung ein

CAS: Vergleichen Sie den Wert im aktuellen Arbeitsspeicher mit dem Wert im Hauptspeicher. Wenn dieser Wert erwartet wird, führen Sie die Operation aus! Wenn dies nicht der Fall ist, führen Sie eine Schleife durch!

Nachteile:

1. Der Zyklus ist zeitaufwändig

2. Nur einmal kann die Atomizität einer gemeinsam genutzten Variablen garantiert werden

3. ABA-Problem

CAS: ABA-Problem (Zibetkatze für Prinz)

Fügen Sie hier eine Bildbeschreibung ein

public class CASDemo {
    
    
    // CAS compareAndSet 比较并交换
    public static void main(String[] args) {
    
    
        AtomicInteger atomicInteger = new AtomicInteger(2020);

        // 期望、更新
        // public final boolean compareAndSet(int expect, int update)
        // 如果期望得值成功了,那么就更新,否则就不更新  CAS是CPU的并发原语。
        // ============== 捣乱的线程 ==================
        System.out.println(atomicInteger.compareAndSet(2020, 2021));
        System.out.println(atomicInteger.get());
        System.out.println(atomicInteger.compareAndSet(2021, 2020));
        System.out.println(atomicInteger.get());
        // ============== 期望的线程 ==================
        System.out.println(atomicInteger.compareAndSet(2020, 6666));
        System.out.println(atomicInteger.get());
    }
}

2. Atomzitat

Lösen Sie das ABA-Problem und führen Sie atomare Referenzen ein! Entsprechender Gedanke: optimistisches Schloss!

Atombetrieb mit Versionsnummer!

public class CASDemo {
    
    
    // AtomicStampedReference 注意,如果泛型是一个包装类,注意对象的引用问题,范围内用同一个,超出自动new新的
	// 正常在业务操作,这里面比较的都是一个个对象
    static AtomicStampedReference<Integer> atomicStampedReference = new
            AtomicStampedReference<>(1, 1);

    // CAS compareAndSet : 比较并交换!
    public static void main(String[] args) {
    
    
        new Thread(() -> {
    
    
            int stamp = atomicStampedReference.getStamp(); // 获得版本号
            System.out.println("a1=>" + stamp);
            try {
    
    
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            atomicStampedReference.compareAndSet(1, 2,
                    atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1);
            System.out.println("a2=>" + atomicStampedReference.getStamp());
            System.out.println(atomicStampedReference.compareAndSet(2, 1,
                    atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1));
            System.out.println("a3=>" + atomicStampedReference.getStamp());
        }, "a").start();
		// 乐观锁的原理相同!
        new Thread(() -> {
    
    
            int stamp = atomicStampedReference.getStamp(); // 获得版本号
            System.out.println("b1=>" + stamp);
            try {
    
    
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            System.out.println(atomicStampedReference.compareAndSet(1, 6,
                    stamp, stamp + 1));
            System.out.println("b2=>" + atomicStampedReference.getStamp());
        }, "b").start();
    }
}

Hinweis:

Integer verwendet den Objekt-Caching-Mechanismus. Der Standardbereich ist -128 ~ 127. Es wird empfohlen, die statische Factory-Methode valueOf zu verwenden, um Objektinstanzen anstelle von new abzurufen, da valueOf das Caching verwendet und new definitiv neue Objekte erstellt und neuen Speicher zuweist Platz;
Fügen Sie hier eine Bildbeschreibung ein

Ich denke du magst

Origin blog.csdn.net/qq_43803285/article/details/115387418
Empfohlen
Rangfolge