Conocimiento profundo de CAS y referencias atómicas

Conocimiento profundo de CAS y referencias atómicas

Una comprensión profunda de CAS

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


    }
}

clase insegura

Inserte la descripción de la imagen aquí

Memoria de operaciones de palabras detrás de la figura anterior

Inserte la descripción de la imagen aquí

CAS: Compare el valor en la memoria de trabajo actual con el valor en la memoria principal, si se espera este valor, entonces realice la operación. Si no es así, ¡siga haciendo bucles!

Desventajas:

1. El ciclo llevará mucho tiempo

2. Solo una vez puede garantizar la atomicidad de una variable compartida

3. Problema de ABA

CAS: problema de ABA (gato de algalia por príncipe)

Inserte la descripción de la imagen aquí

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. Cotización atómica

¡Resuelva el problema de ABA e introduzca referencias atómicas! Pensamiento correspondiente: ¡cerradura optimista!

¡Operación atómica con número de versión!

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

Nota:

Integer usa el mecanismo de almacenamiento en caché de objetos, el rango predeterminado es -128 ~ 127, se recomienda usar el método de fábrica estático valueOf para obtener instancias de objetos en lugar de nuevas, porque valueOf usa almacenamiento en caché, y new definitivamente creará nuevos objetos y asignará nueva memoria espacio;
Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_43803285/article/details/115387418
Recomendado
Clasificación