结论:区别仅在于返回的结果,修改的值是相同的,但是返回的值不同。

看一下源码注释

 1    /**
2 * Atomically adds the given value to the current value.
3 *
4 * @param delta the value to add
5 * @return the updated value
6 */
7 public final int addAndGet(int delta) {
8 return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
9 }
10
11 /**
12 * Atomically adds the given value to the current value.
13 *
14 * @param delta the value to add
15 * @return the previous value
16 */
17 public final int getAndAdd(int delta) {
18 return unsafe.getAndAddInt(this, valueOffset, delta);
19 }

  注意看下划线,一个是更新后的值,一个是更新前的值

源码:(sun.misc.Unsafe#getAndAddInt)

1   public final int getAndAddInt(Object object, long offset, int update) {
2 int expect;
3 do {
4 expect = this.getIntVolatile(this, offset);
5 } while (!this.compareAndSwapInt(this, offset, expect, expect + update));
6
7 return expect;
8 }

  传入的形参就不必解释了,对照上面的代码应该能看懂

  第二行,期望值

  第四行,取内存(堆)中的数据

  第五行,首先肯定要执行cas,然后就是根据返回值决定是否要继续执行。

    这里有必要解释cas的执行过程,如下

1 int compare_and_swap(int *mem_val, int expect, int update)
2 {
3 int old_val;
4 old_val = *mem_val;
5 if(old_val == expect) *mem_val = update;
6 return old_val;
7 }

   主要就是第五行,如果内存中的值和传进来的期望值相同,那就把内存中的值赋值为要更新的值,然后返回内存值。

  可能有人对参数坑位有疑惑,这个问题其实仔细思考就能猜到。

  object + offset => 定位到内存中对象属性的值

   这样,也就能和内存值关联上了

写个demo试试

 1 import java.util.concurrent.atomic.AtomicInteger;
2
3 /**
4 * @author Alin
5 * @date 2020/7/26
6 */
7 public class TestAtomicInt {
8 static AtomicInteger count = new AtomicInteger(0);
9
10 public static void main(String[] args) {
11 //返回新值
12 System.out.println(count.addAndGet(20));
13 System.out.println("\tcur = " + count.get());
14 /**
15 * public final int getAndAddInt(Object this, long offset, int update) {
16 * int expect;
17 * do {
18 * expect = this.getIntVolatile(this, offset);
19 * } while(!this.compareAndSwapInt(this, offset, expect, expect + update));
20 *
21 * return expect;//返回旧值
22 * }
23 */
24 System.out.println(count.getAndAdd(2));
25 //返回当前值
26 System.out.println("\tcur = " + count.get());
27
28 }
29 }

 结果 

  20

    cur = 20

  20

     cur = 22

AtomicInteger的addAndGet(int delta)与getAndAdd(int delta)有什么区别?的更多相关文章

  1. C语言复杂声明-void (*signal(int sig, void (*handler)(int)))(int);

    问题提出 请分析此声明:void (*signal(int sig, void (*handler)(int)))(int); 求解过程 在对上面的例子作分析之前,我们需要了解C语言的声明优先级,&l ...

  2. 编写Java应用程序。首先,定义描述学生的类——Student,包括学号(int)、 姓名(String)、年龄(int)等属性;二个方法:Student(int stuNo,String name,int age) 用于对对象的初始化,outPut()用于输出学生信息。其次,再定义一个主类—— TestClass,在主类的main方法中创建多个Student类的对象,使用这些对象来测 试Stud

    package zuoye; public class student { int age; String name; int stuNO; void outPut() { System.out.pr ...

  3. const int * p 和 int const * p 和 int * const p 的区别

    首先注意,const int * p 和int const *p 是一样的,并且不管是不是*p,即使const int i和int const i也是一样的,所以我们接下来只讨论int const * ...

  4. (int),Int32.Parse() 和 Convert.toInt32() 的区别

    在 C# 中,(int),Int32.Parse() 和 Convert.toInt32() 三种方法有何区别? int 关键字表示一种整型,是32位的,它的 .NET Framework 类型为 S ...

  5. (int &)a 和(int)a

      [cpp] view plain copy float a = 1.0f;     cout < < (int)a < < endl;     cout < < ...

  6. C++中int *p[4]和 int (*q)[4]的区别

    这俩兄弟长得实在太像,以至于经常让人混淆.然而细心领会和甄别就会发现它们大有不同. 前者是指针数组,后者是指向数组的指针.更详细地说. 前: 指针数组;是一个元素全为指针的数组.后: 数组指针;可以直 ...

  7. int * const 与 const int * 的区别

    type * const 与 const type * 是在C/C++编程中特别容易混淆的两个知识点,现在就以 int * const 和 const int * 为例来简略介绍一下这两者之间的区别. ...

  8. open_clientfd(char* hostname,int port)和open_listenfd(int port)

    #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h&g ...

  9. 如何理解这段代码:void (*signal (int sinno,void(*func)(int)))(int)

    void (*signal (int sinno,void(*func)(int)))(int) 先来看void(*func)(int)   这里的意思是声明一个函数指针func,它的参数类型为int ...

随机推荐

  1. php 实现签名验签

    本人php菜鸟,主要使用php实现简单的签名验签功能 以下php代码使用的密钥格式为pem格式,其他证书格式可以使用openssl进行转换(未安装请实现安装): 以下是.p12文件导出pem格式公私钥 ...

  2. php 断点续传以及100% 后台zip解压

    前台部分 <div class="col-md-12"> <div class="form-group"> <label clas ...

  3. python爬虫10 b站爬取使用 selenium+ phantomJS

    但有时候 我们不想要让它打开浏览器去执行 能不能直接在代码里面运行呢 也就是说 有没有一个无形的浏览器呢 恩 phantomJS 就是 它是一个基于 WebKit 的浏览器引擎 可以做到无声无息的操作 ...

  4. 咀嚼Lock和Synchronized锁

    1.Synchronized锁 底层是monitor监视器,每一个对象再创建的时候都会常见一个monitor监视器,在使用synchronized代码块的时候,会在代码块的前后产生一个monitorE ...

  5. Facebook 的神仙组长什么样?

    这里是<齐姐聊大厂>系列的第 14 篇 每周五早上 8 点,与你唠唠大厂的那些事 号外号外!前 12 篇已出 PDF:公粽号后台回复「大厂」即可获得! ❝ 小齐说: 这篇文章是来自阿米粥的 ...

  6. 使用python和numpy实现函数的拟合

    给出一个数组x,然后基于一个二次函数,加上一些噪音数据得到另一组数据y. 将得到的数组x,y,构建一个机器学习模型,采用梯度下降法,通过多次迭代,学习到函数的系数.使用python和numpy进行编程 ...

  7. linux系统中离线安装python3.7过程记录

    最近公司新弄来一台linux  redhat 4.4.7服务器,准备在上面离线安装python3.7,安装过程中出现一些问题,特此记录下来. 首先在python官网上下载了 Python-3.7.3. ...

  8. zabbix自动发现的python方式数据生成

    前言 zabbix里面有个功能是自动发现,比如文件系统和网卡的获取的时候,因为预先无法知道这个网卡的名称,所以就有了这个自动发现的功能,这里我是因为要用到存储池的自动发现,所以需要对数据进行生成 实现 ...

  9. 流量控制--5.Classless Queuing Disciplines (qdiscs)

    Classless Queuing Disciplines (qdiscs) 本文涉及的队列规则(Qdisc)都可以作为接口上的主qdisc,或作为一个classful qdiscs的叶子类.这些是L ...

  10. Function(函数分享)第二节

    一.类型注解 1.1 类型注解 函数的类型注解分为两个部分:参数类型注解和返回值类型注解.其中返回值类型注解有时候我们可以直接省略,因为Typescript可以根据返回的语句来自动判断出返回值的类型. ...