一个比较明显的事实就是 i++ 本身不是原子性的,所以在多线程的环境中, i++ 会导致最终输出的值不符合我们的预期。

    1. public class AtomicTest {
    2. public static int value = 1;
    3. public static void main(String[] args) {
    4. for (int i = 0; i < 1000000; i++) {
    5. new Thread(AtomicTest::handle).start();
    6. }
    7. }
    8. public static void handle() {
    9. value = value + 1;
    10. System.out.println(value); //>> 我机器输出的结果是999997。
    11. }
    12. }

    而AtomicInteger就可以解决在多线程并发的情况下 i++ 是原子性的,最终的输出结果是符合我们的预期的。例如上边的代码在我循环100w次的事实输出的结果是999997,而使用 AtomicInteger 进行更新的时候是符合预期的。

    AtomicInteger 内部则是使用 unsafe 来进行cas操作。

    我们不能直接使用unsafe了,只能通过反射的方式来获取unsafe。然后在来使用它,当然正常情况下我们是用不到的

    1. public final int incrementAndGet() {
    2. return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    3. }

    而在unsafe内部,则是使用的死循环的 cas , 每次都从主内存中获取对应数据,然后比较更新。

    1. public final int getAndAddInt(Object var1, long var2, int var4) {
    2. int var5;
    3. do {
    4. var5 = this.getIntVolatile(var1, var2);
    5. } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
    6. return var5;
    7. }
    • getIntVolatile native 实现
    • compareAndSwapInt native实现