这里我们看下addAndGet方法
上源码
public final int addAndGet(int var1) { return unsafe.getAndAddInt(this, valueOffset, var1) + var1; }
调用的Unsafe类,这个类是直接操作内存的。继续跟进Unsafe.getAndSetInt
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; }
这个方法就是为什么保证线程安全。
首先第一参数是AtomicInteger值本身,第二个参数是内存中的偏移量,第三个参数是addAndGet传入的值,也就是要加的数。
循环去拿对象本身在内存偏移量后的值,循环条件是compareAndSwapInt返回false,如果为true则跳出循环。
compareAndSwapInt是CAS 比较&交换,如果偏移量的值跟取到的var5值相等,那么就var5 + var4替换var1,这步是原子性的。
当多个线程同时进入var5 = this.getIntVolatile(var1, var2);,都拿到了相同的偏移量后的值,但是compareAndSwapInt是原子性的,一定会有一个线程先改变了偏移量后的值,那么其他线程就会compareAndSwapInt返回false,继续去拿修改后的值,然后继续compareAndSwapInt,直到它执行一次循环没有其他线程改变这个值,那么才会修改成功。