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

看一下源码注释

 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. abp(net core)+easyui+efcore实现仓储管理系统——出库管理之五(五十四)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统--ABP总体介绍(一) abp(net core)+ ...

  2. Java_枚举

    枚举 JDK1.5引入枚举类型, 枚举类型的定义包括枚举的声明和枚举体 enum Season { SPRING, SUMMER, AUTUMN, WINDER } 所有的枚举类型隐性的继承来自jav ...

  3. C#实现的几种委托方式介绍

    //普通委托            DeleteShow ds = new DeleteShow(ShowName);            Console.WriteLine("----- ...

  4. C++ 设计模式 4:行为型模式

    0 行为型模式 类或对象怎样交互以及怎样分配职责,这些设计模式特别关注对象之间的通信. 1 模板模式 模板模式(Template Pattern)定义:一个抽象类公开定义了执行它的方法的方式/模板.它 ...

  5. 准备数据集用于flink学习

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. 如何让Visual Studio 2019更好用(VS2019配置指南)

    今天电脑没带,借用外面的电脑配环境来用.刚下载完的VS是这样的: UI挺好看的,但代码窗口看起来就和上个世纪的VC6没什么区别,快捷键用起来也不顺手.(2333) 接下来,我们将一步步优化编写环境,让 ...

  7. TCP拥塞控制原理

    一.何为拥塞 路由器无法处理高速到达的数据而被迫丢弃数据的现象叫做拥塞. 二.何为拥塞控制 TCP流量控制时为了平衡一个链接中接收方和发送方的速度匹配问题,当发送方发现发送速度大于接收方的接收速度时动 ...

  8. 使用flexbox的自适应照片布局

    作者:Tim Vam Damme 让我们来看看一种超轻量级的方法,它可以为一组任意大小的照片创建水平砖砌效果.将任何照片丢到上面,它们将边对边无缝对齐. 该解决方案不仅轻巧,而且非常简单.我们将使用无 ...

  9. 2. RDD(弹性分布式数据集Resilient Distributed dataset)

    *以下内容由<Spark快速大数据分析>整理所得. 读书笔记的第二部分是讲RDD.RDD 其实就是分布式的元素集合.在 Spark 中,对数据的所有操作不外乎创建RDD.转化已有RDD以及 ...

  10. HarmonyOS Java UI之DirectionalLayout布局

    在之前的章节中我使用的是Java 代码构建UI界面,从本节开始,将使用XML构建UI界面. 使用XML构建UI(默认你已经会在项目中创建XML布局文件)界面相对Java代码构建的好处是:结构清晰,代码 ...