概念
比较并交换,简单来说,预期值与内存的值比较,相等则更新,否则循环下去
理解
内存里存的一个值,你拿去,在更新的时候调用,如果这期间没人动过这个值,你可以更新,
否则,重复操作,直至成功。
对一个值自增的自旋操作,伪代码如下:
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
提供了依据版本号判断变化的实现。