GetAndIncrement de AtomicInteger es equivalente a i ++, ¿por qué puede garantizar la atomicidad?

Estudie el código fuente subyacente de este método
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

AtomicInteger usa CAS pero no necesita estar sincronizado

La coherencia con sincronizados está garantizada, pero la simultaneidad ha disminuido mucho.
Usamos CAS para usar do ... mientras que para hacer juicios repetidos para asegurar la coherencia y no reducir la simultaneidad.
CAS ----> compare And Swap, es una primitiva de concurrencia de CPU. No se le permite ser interrumpido durante el proceso de ejecución, lo que significa que CAS es una instrucción atómica en la CPU y no causará inconsistencia en los datos.
Desventajas de CAS:
1. En un entorno de alta concurrencia, agregar un bucle while para juzgar sin éxito hace que el costo de la taza sea extremadamente alto.
2. Solo garantizar la atomicidad de una variable compartida no puede garantizar un fragmento de código.
3. Puede causar problemas de ABA
Cuatro palabras resumen el gato de algalia para el príncipe.
Si t1 y t2 operan en los datos A al mismo tiempo, t1 cambia los datos A por B y los actualiza a la memoria principal, pero t2 no lo sabe en este momento, t1 ha actualizado B a A, y luego t2 va a la memoria principal. Desde la memoria, A todavía está bien, así que cambié la A en la memoria principal a sus propios datos. Este es el problema de ABA

Lenguaje ensamblador de bajo nivel
Inserte la descripción de la imagen aquí

La solución al problema de ABA:

Existe una clase AtomicStampedReference en la clase atómica que puede resolver este problema con un número de versión.

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


    }
}

Supongo que te gusta

Origin blog.csdn.net/qq_36905956/article/details/105857254
Recomendado
Clasificación