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

 

posted @ 2020-07-26 16:29  夜旦  阅读(3498)  评论(0编辑  收藏  举报