AtomicInteger的addAndGet(int delta)與getAndAdd(int delta)有什麼區別?
阿新 • • 發佈:2020-07-26
結論:區別僅在於返回的結果,修改的值是相同的,但是返回的值不同。
看一下原始碼註釋
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