ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CAS与AtomicInteger自增操作

2021-03-05 16:30:54  阅读:387  来源: 互联网

标签:var5 自增 var1 var2 CAS AtomicInteger int 对象 expect


CAS:compareAndSet,对比然后赋值;

AtomicInteger中的:

  /**
    *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;

标签:var5,自增,var1,var2,CAS,AtomicInteger,int,对象,expect
来源: https://blog.csdn.net/weixin_43732749/article/details/114399601

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有