CAS与AtomicInteger自增操作

CAS:compareAndSet,对比然后赋值;

AtomicInteger中的:

  /**
    *Unsafe类是用来调用native方法,实现对操作系统底层硬件操作
    *this:操作对象
    *valueOffset:对象值偏移地址
    *expect:预期值
    *update:更新的值
    *
    */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

过程就是通过对象this以及值内存偏移量获取到对象目前真正的值,然后与expect比较,如果相等,就更新值为update,并返回true;如果内存中的值与预期值expect不相等,则不做修改,返回false;
很有乐观锁的感觉;

然后看一下AtomicInteger的原子性自增;

    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }

点进getAndAddInt

/**
*var1:操作对象
*var2:对象值偏移地址
*var4:增加的值
*var5:获取对象的目前的值
**/
    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }

过程是:

  1. 根据对象以及偏移量,让var5获取对象的值
  2. compareAndSwapInt就是上面的CAS原子性操作,比较对象目前的值是否等于var5,再决定是否修改;如果compareAndSwapInt返回true,则自增成功,输入新值,并跳出循环;而如果为false,则自增失败,重新跳回第一步,重新执行;

之所以还要获取最新的值与var5比较,就是为了防止多线程下,有其它线程先对数据进行修改,导致出现错误的结果;这个也是在多线程下,AtomicInteger自增能正确的原因;

而普通的n++操作是不具有原子性操作的,因为这个并不是一条指令完成的;
流程是:
1.先取出n的值;
2.然后让n+1;
3.之后在将n的值写回去;
则在多线程的情况下,就不能保证这三条指令连接一起完成;

假设情况:n=0
线程A先取出n=0;
然后转为线程B,B也取出n=0,B将0+1=1然后存进去;
又转回线程A,此时A拿到的n仍然等于0,所以A将0+1=1存了进去;
则AB都对n做自增操作,但n最后等于1;

最后记录一下ABA问题,意思和ABA很像,就是某对象值=A,然后被修改成B在,再被修改回A,则其他线程可能会认为对象的值没有变化,而实际上值已经被修改过了;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值