概念
比較並交換,簡單來說,預期值與內存的值比較,相等則更新,否則循環下去
理解
內存里存的一個值,你拿去,在更新的時候調用,如果這期間沒人動過這個值,你可以更新,
否則,重復操作,直至成功。
對一個值自增的自旋操作,偽代碼如下:
public final int getAndIncrement() { for (;;) { int current = get(); // 取得內存里數值 int next = current + 1; // 加1 if (compareAndSet(current, next)) // 調用compareAndSet執行原子更新操作 return current; } }
結合例子
黑盒,存一個數字i,初始為0
線程A,B,C
線程A,
第一次自旋:去黑盒拿一個數字,假設這時候為0,B和C拿到值為0,還未更新i值,A更新是(expect:0, update:1),執行成功,此時黑盒里i為1
線程B,
第一次自旋:執行(expect:0, update:1),因為這時候被A更新為1了,所以失敗,
第二次自旋:再去拿值,這時候拿到的是1,假設這時候C還未更新,執行(expect:1,update:2),更新成功,此時黑盒里i為2
線程C,
第一次自旋失敗,原因如B
第二次自旋:因為被B搶先了,所以也失敗
第三次自旋:拿到的值為2,執行(expect:2,update:3),成功
總結
自旋的意思,多個線程奪取鎖,那就必須先讓自己得到的值跟內存的值一樣才能操作
ABA問題
線程A拿到的值是X,但X有可能被另一個線程B改為Y,又改為X,線程A這種情況下視為沒有發生過變化,其實變化了,對此,AtomicStampedReference
提供了依據版本號判斷變化的實現。