原子类AtomicInteger的ABA

ABA问题的产生

CAS会导致ABA问题

CAS算法实现一个重要前提需要去除内存中某时刻的数据并在当下时刻进行比较并替换,那么在这个时间差类会导致数据的变化,比如说一个线程one从内存位置V中取出A,这个时候另一个线程two也从内存中取出A,并且线程two进行了一些操作将值变成了B,然后线程two线程又将V位置的数据编程A,这时候线程one进行CAS操作发现内存中仍然是A,然后线程one操作成功。

尽管线程one的CAS操作成功,但是不代表这个过程就是没有问题的。

原子引用

AtomicReferenceDemo

package com.liang.cas;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.concurrent.atomic.AtomicReference;

@AllArgsConstructor
@Data
class User{
    private String username;
    private String password;
}
public class AtomicReferenceDemo {
    public static void main(String[] args) {
        User user1 = new User("张三","123");
        User user2 = new User("李四","123");
        AtomicReference<User> atomicReference = new AtomicReference<>();
        atomicReference.set(user1);
        System.out.println(atomicReference.compareAndSet(user1, user2)+"\t"+atomicReference.get().toString());
        System.out.println(atomicReference.compareAndSet(user1, user2)+"\t"+atomicReference.get().toString());
    }
}

在这里插入图片描述

ABA 问题是怎么产生的

package com.liang.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class ABADemo {
    private static AtomicInteger atomicInteger = new AtomicInteger(100);

    public static void main(String[] args) {
        new Thread(()->{
            atomicInteger.compareAndSet(100,101);
            atomicInteger.compareAndSet(101,100);
        },"one").start();


        new Thread(()->{
            try {
                //保证上面的线程运行
                TimeUnit.SECONDS.sleep(3);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            atomicInteger.compareAndSet(100,2020);
            System.out.println(atomicInteger.get());  //2020
        },"one").start();
    }
}

在这里插入图片描述

当有一个值从 A 改为 B 又改为 A,这就是 ABA 问题。

时间戳原子引用

package com.liang.cas;

import java.util.concurrent.atomic.AtomicStampedReference;

public class ABADemo1 {
    private 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 {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            atomicStampedReference.compareAndSet(100, 101, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1 );
            atomicStampedReference.compareAndSet(101, 100, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1 );
        }).start();

        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + " 的版本号为:" + stamp);
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            boolean b = atomicStampedReference.compareAndSet(100, 2019, stamp, stamp + 1);
            System.out.println(b); // false
            System.out.println(atomicStampedReference.getReference()); // 100
        }).start();
    }
}

在这里插入图片描述
修改失败
我们先保证两个线程的初始版本为一致,后面修改是由于版本不一样就会修改失败。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值