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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM