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 ...
随机推荐
- php 实现签名验签
本人php菜鸟,主要使用php实现简单的签名验签功能 以下php代码使用的密钥格式为pem格式,其他证书格式可以使用openssl进行转换(未安装请实现安装): 以下是.p12文件导出pem格式公私钥 ...
- MySQL日期函数与日期转换格式化函数大全
Mysql作为一款开元的免费关系型数据库,用户基础非常庞大,本文列出了MYSQL常用日期函数与日期转换格式化函数 1.DAYOFWEEK(date) 1 2 SELECT DAYOFWEEK('201 ...
- slam-g2o安装失败的解决问题
1.安装依赖项libqglviewer-dev出问题 原因: ubuntu16.04或者14.04不能直接sudo apt-get install libqglviewer-dev. 使用三个包来安装 ...
- Pycharm激活码,2020年9月29日最新激活码
分享一个Pycharm激活码给大家: 5MJ8MJ2T1Q-eyJsaWNlbnNlSWQiOiI1TUo4TUoyVDFRIiwibGljZW5zZWVOYW1lIjoi6I635Y+W77yaIG ...
- C++ 基础 6:模板
1 函数模板 泛型(Generic Programming),即是指具有在多种数据类型上皆可操作的含意. 泛型编程 的代表作品 STL 是一种高效.泛型.可交互操作的软件组件. 泛型编程最初诞生于 C ...
- 【转】Lisp的本质
Lisp的本质: http://www.csdn.net/article/2012-11-22/2812113-The-Nature-Of-Lisp###
- linux的别名(alias/unalias)
linux中有别名时先找的别名后找命令文件 临时创建是直接用alias. [root@localhost ~]# alias ls=pwd [root@localhost ~]# ls /root 其 ...
- WPF控件库总结
前言 在使用WPF项目的时候, 一般首要的就是对UI部分的选型, 而WPF相关的UI控件和样式库在Githu也是非常多. 关于UI的部分,可以分为二种: 对控件本身没有很大的需求, 只需要在原有的基础 ...
- SMTPAuthenticationError: (535, '5.7.8 authentication failed')解决办法
代码: 运行之后一直报错,SMTPAuthenticationError: (535, '5.7.8 authentication failed'). 查找半天是因为新浪邮箱的STMP的服务没有开启, ...
- [LeetCode题解]143. 重排链表 | 快慢指针 + 反转
解题思路 找到右边链表,再反转右边链表,然后按左.右逐一合并 代码 /** * Definition for singly-linked list. * public class ListNode { ...