AtomicInteger的addAndGet(int delta)与getAndAdd(int delta)有什么区别?
结论:区别仅在于返回的结果,修改的值是相同的,但是返回的值不同。
看一下源码注释
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)有什么区别?的更多相关文章
- C语言复杂声明-void (*signal(int sig, void (*handler)(int)))(int);
问题提出 请分析此声明:void (*signal(int sig, void (*handler)(int)))(int); 求解过程 在对上面的例子作分析之前,我们需要了解C语言的声明优先级,&l ...
- 编写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 ...
- const int * p 和 int const * p 和 int * const p 的区别
首先注意,const int * p 和int const *p 是一样的,并且不管是不是*p,即使const int i和int const i也是一样的,所以我们接下来只讨论int const * ...
- (int),Int32.Parse() 和 Convert.toInt32() 的区别
在 C# 中,(int),Int32.Parse() 和 Convert.toInt32() 三种方法有何区别? int 关键字表示一种整型,是32位的,它的 .NET Framework 类型为 S ...
- (int &)a 和(int)a
[cpp] view plain copy float a = 1.0f; cout < < (int)a < < endl; cout < < ...
- C++中int *p[4]和 int (*q)[4]的区别
这俩兄弟长得实在太像,以至于经常让人混淆.然而细心领会和甄别就会发现它们大有不同. 前者是指针数组,后者是指向数组的指针.更详细地说. 前: 指针数组;是一个元素全为指针的数组.后: 数组指针;可以直 ...
- int * const 与 const int * 的区别
type * const 与 const type * 是在C/C++编程中特别容易混淆的两个知识点,现在就以 int * const 和 const int * 为例来简略介绍一下这两者之间的区别. ...
- open_clientfd(char* hostname,int port)和open_listenfd(int port)
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h&g ...
- 如何理解这段代码:void (*signal (int sinno,void(*func)(int)))(int)
void (*signal (int sinno,void(*func)(int)))(int) 先来看void(*func)(int) 这里的意思是声明一个函数指针func,它的参数类型为int ...
随机推荐
- vbox复制虚拟机之后修改ethx号使得可以上网
vbox复制虚拟机之后修改ethx号使得可以上网: (1).改硬件mac编号[此项需要重启] vi /etc/udev/rules.d/70-persistent-net.rules 然后删掉上面一行 ...
- Netlink 内核实现分析 3
Netlink IPC 数据结构 #define NETLINK_ROUTE 0 /* Routing/device hook */ #define NETLINK_UNUSED 1 /* Unuse ...
- 《GNU_makefile》第六章——变量
makefile中的变量特征和C语言中的宏一样. 变量使用 =,:=,?= 和 define 定义 一些特殊的自动化变量:$< $@ $^ $* 1.变量的引用 通过 $(VAR) 或 ${VA ...
- Loadrunner学习(一)
一个优秀的软件系统不单单具有良好的功能,还需要有过硬的性能,一个只通过功能测试的系统,只能称之为"可用",而不能算是"好用".当然,性能测试需要基于功能测试,只 ...
- Ceph 状态报警告 pool rbd has many more objects per pg than average (too few pgs?)
定位问题 [root@lab8106 ~]# ceph -s cluster fa7ec1a1-662a-4ba3-b478-7cb570482b62 health HEALTH_WARN pool ...
- python学习--sys.argv
sys.argv是获取命令行参数的: sys.argv[0]表示代码本身文件路径:从1开始获取参数. import sysprint (sys.argv[0])count = int(sys.argv ...
- 分布式监控系统之Zabbix宏、模板和自定义item
前文我们聊了下zabbix的基础使用,包括主机的添加.监控项.触发器.action以及告警通知的配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/140073 ...
- 04、MyBatis DynamicSQL(Mybatis动态SQL)
1.动态SQL简介 动态 SQL是MyBatis强大特性之一. 动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似. MyBatis 采用功能强大的基于 OGNL 的表达式来 ...
- 打包错误:Failed to execute goal org.scala-tools:maven-scala-plugin:2.15.2:compile (default) on project MusicProject: wrap: org.apache.commons.exec.ExecuteException:
错误:Failed to execute goal org.scala-tools:maven-scala-plugin:2.15.2:compile (default) on project Mus ...
- 兄弟萌,这份SpringMVC框架学习笔记真的建议反复看,写的太细了
概述 是Spring为展现层提供的基于MVC设计理念的Web框架,通过一套MVC注解,让POJO成为处理请求的控制器,而无需实现任何接口 支持REST风格的URL请求 采用松散耦合的可插拔组件结构,比 ...