CAS之AtomicStampedReference介绍及使用

介绍

AtomicStampedReference是jdk提供的用于cas操作引用类型的一个类,相比于AtomicReference而已可以解决ABA问题,解决的原理就是用两个参数来对比是否做了更改,而第二个参数是个int值,只要保证第二个int值一直累加即不会存在aba问题

使用

场景:对一个Integer类型的对象cas自增

public class CasDemo {

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

    public static void main(String[] args) {
        // 必定成功,原子性操作
        boolean result = increment();
        System.out.println(result);
    }


    /**
     * 自增+1
     */
    public static boolean increment() {
    	// 死循环,直到cas成功
        for (;;) {
            // 必须先get出来,不能在compareAndSet里面在get,否则不能保证多个get获取到的是不同值
            Integer i1 = atomicStampedReference.getReference();
            int s1 = atomicStampedReference.getStamp();
            Integer i2 = i1 + 1;
            int s2 = atomicStampedReference.getStamp() +1;
            boolean result = atomicStampedReference.compareAndSet(i1,i2,s1,s2);
            // 失败则继续循环
            if (result) {
                return true;
            }
        }
    }

}

ABA问题

ABA问题是CAS机制中出现的一个问题,就是说一个线程把数据A变为了B,然后又重新变成了A。此时另外一个线程读取的时候,发现A没有变化,就误以为是原来的那个A。这就是有名的ABA问题。
案例
如共享变量A初始值1,线程1需要对A做自增1,线程2需要把A修改为10,线程3需要把A修改为1
1、线程1读取到A的值是1,此时还没有执行自增+1,线程2和线程3并发执行了
2、线程2把A的值修改为了10
3、线程3把A的值修改为了1
4、此时线程1准备对A的值+1,线程A执行CAS(Compare and Swap,即比较再交换),比较时发现A的值是之前读取到的值1,发现相等,执行+1,执行结束
此时虽然线程1执行成功了,但是线程A执行比较时的A的状态其实并不是线程1之前读取到的A的状态了,这就是ABA问题
ABA问题导致的原因,是CAS过程中只简单进行了“值”的校验,再有些情况下,“值”相同不会引入错误的业务逻辑(例如库存),有些情况下,“值”虽然相同,却已经不是原来的数据了。

并不是所有场景在出现ABA都会存在问题,如果上述场景就不会,线程1只不过是想对A自增1,上述场景即使出现ABA问题,仍然不影响业务

至于ABA问题在哪些场景需要避免,还是需要根据具体业务判断

扩展

对于一些常见类型推荐使用相对应的cas类,如AtomicInteger、AtomicLong、AtomicBoolean

原创不易,转载请说明出处https://editor.csdn.net/md?articleId=107030155

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值