今天面试被问了CAS原理,我的回答是
数据做更改时会用一个递增的版本号判断数据是否发生过改变,如果已经发生过改变自旋直至到最新值然后变更;
这里有两个地方我一直理解错误:
1.版本号是自增的,所以我一直没理解为什么CAS会导致ABA问题
2.CAS会自旋直至最新值做更新,后来其实是AtomicInteger调用Unsafe做得事情(虽然之前有看过源码,但是被错误思想先入为主了)
// 代码1:AtomicInteger add方法 public final int getAndAdd(int delta) { return unsafe.getAndAddInt(this, valueOffset, delta); } // 代码2:add对应Unsafe方法 public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2); } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); return var5; } // 代码3:AtomicInteger set方法 public final int getAndSet(int newValue) { return unsafe.getAndSetInt(this, valueOffset, newValue); } // 代码4:set对应Unsafe方法 public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2); // this.compareAndSwapInt(var1, var2, var5, var5 + var4) // var1代表当前AtomicInteger实例对象 // var2内存偏移量,简单理解为var1的内存地址,赋值代码是AtomicInteger static 代码块 具体见代码5 // var5预期的旧值 // var5 + var4 成功更改后的新值 } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); return var5; } // 代码5:Integer private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; static { try { valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } }