Problema de CAS ABA y su solución

¿Cuál es el problema de CAS ABA?

Un hilo T1 toma A de la ubicación de memoria V, en este momento otro hilo T2 también toma A de la memoria, y T2 realiza algunas operaciones para convertirse en B, y luego dos convierte los datos en la ubicación V en A. T1 realiza la operación CAS y encuentra que A todavía está en la memoria, y luego la operación T1 es exitosa. Aunque la operación CAS del subproceso T1 es exitosa, no significa que este proceso no sea un problema.
Inserte la descripción de la imagen aquí

La raíz del problema ABA es que cuando CAS modifica una variable, no puede registrar el estado de la variable, como el número de modificaciones y si la variable ha sido modificada. De esta manera, es fácil modificar B a A nuevamente cuando un hilo cambia de A a B, lo que causa el problema de múltiples ejecuciones de CAS.

El código simula el problema ABA

public class ABADemo {

    static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
    
    public static void main(String args[]) {
        System.out.println("模拟ABA问题:");
        new Thread(() -> {
            // ABA
            atomicReference.compareAndSet(100, 101);
            atomicReference.compareAndSet(101, 100);
        }, "T1").start();

        new Thread(() -> {
            try {
                // 暂停一秒钟,保证T1线程干完所有事情
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(atomicReference.compareAndSet(100, 2019) + " 当前" + atomicReference.get());
        }, "T2").start();
	}
}

Inserte la descripción de la imagen aquí

¿Cómo resolver el problema ABA?

Use la función compareAndSet de AtomicStampedReference, que tiene cuatro parámetros:

compareAndSet (V esperadoReferencia, V nuevaReferencia, int esperadoStamp, int nuevoStamp)
(1) El primer parámetro esperadoReferencia: indica el valor esperado.
(2) El segundo parámetro newReference: indica el valor a actualizar.
(3) El tercer parámetro esperado Marca: indica la marca de tiempo esperada.
(4) El cuarto parámetro newStamp: indica la marca de tiempo que se actualizará.

public class ABADemo {

    static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1);

    public static void main(String args[]) {
        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + " 第一次版本号:" + stamp);
            try {
                // 暂停一秒钟T3,等待T4拿到相同的版本号
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // ABA
            atomicStampedReference.compareAndSet(100, 101, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
            System.out.println(Thread.currentThread().getName() + " 第二次版本号:" + atomicStampedReference.getStamp());

            atomicStampedReference.compareAndSet(101, 100, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
            System.out.println(Thread.currentThread().getName() + " 第三次版本号:" + atomicStampedReference.getStamp());
        }, "T3").start();

        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + " 第一次版本号:" + stamp);
            try {
                // 暂停三秒钟T4
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            boolean result = atomicStampedReference.compareAndSet(100, 2019, stamp, stamp + 1);
            System.out.println("当期T4的版本号:" + stamp);
            System.out.println("当期主存的真实版本号:" + atomicStampedReference.getStamp());
            System.out.println(Thread.currentThread().getName() + "修改成功否:" + result + " 当前值:" + atomicStampedReference.getReference());
        }, "T4").start();
    }
}

Inserte la descripción de la imagen aquí

GitHub: demostración multiproceso

Publicado 83 artículos originales · ganado elogios 23 · vistas 3524

Supongo que te gusta

Origin blog.csdn.net/qq_44779506/article/details/105539767
Recomendado
Clasificación