一个比较明显的事实就是 i++ 本身不是原子性的,所以在多线程的环境中, i++ 会导致最终输出的值不符合我们的预期。
public class AtomicTest {public static int value = 1;public static void main(String[] args) {for (int i = 0; i < 1000000; i++) {new Thread(AtomicTest::handle).start();}}public static void handle() {value = value + 1;System.out.println(value); //>> 我机器输出的结果是999997。}}
而AtomicInteger就可以解决在多线程并发的情况下 i++ 是原子性的,最终的输出结果是符合我们的预期的。例如上边的代码在我循环100w次的事实输出的结果是999997,而使用 AtomicInteger 进行更新的时候是符合预期的。
AtomicInteger 内部则是使用 unsafe 来进行cas操作。
我们不能直接使用unsafe了,只能通过反射的方式来获取unsafe。然后在来使用它,当然正常情况下我们是用不到的
public final int incrementAndGet() {return unsafe.getAndAddInt(this, valueOffset, 1) + 1;}
而在unsafe内部,则是使用的死循环的 cas , 每次都从主内存中获取对应数据,然后比较更新。
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;}
- getIntVolatile native 实现
- compareAndSwapInt native实现
