1. 程式人生 > 實用技巧 >AtomicInteger的addAndGet(int delta)與getAndAdd(int delta)有什麼區別?

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 object + long 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