JUC学习记录(二)- AtomicInteger

AtomicInteger

内部调用了Unsafe的方法,保证原子性;

什么是原子性:指操作要么成功要么失败(失败则进行事务回滚)

从一个例子从开始学习AtomicInteger
  Executor executor = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executor.execute(() -> {
                for (int j = 0; j < 30; j++) {
                    a++;
                    System.out.println(atomicInteger.incrementAndGet());
                }

            });
        }

其中a的值最终小于300,而atomicInteger最终输出的值为300(顺序不定)。

a++其实可以分解成3个步骤:

  1. 从主存读取a
  2. a+1操作
  3. 将结果刷新到主存

而在多线程中,某一线程进行了a+1但是值还没刷新到主存中另一个线程又执行了读取的操作,从而导致最终的结果小于300,而atomicInteger则不存在此风险,下面分析它为什么不存在此风险。

我们看其主要的变量以及常用的API来分析它内部是如何实现的:

变量
    // 获取Unsafe实例
    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
    // 通过Unsafe获取value的内存偏移量
    private static final long VALUE;

    static {
        try {
            VALUE = U.objectFieldOffset
                // 获取类中value变量的内存偏移量
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (ReflectiveOperationException e) {
            throw new Error(e);
        }
    }
    // 值
    private volatile int value;
常用API

从例子中的方法开始分析:

    /**
     * 实际调用Unsafe的方法 - CAS 
     * 
     * Atomically increments by one the current value.
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
        // VALUE是当前值的偏移量
        return U.getAndAddInt(this, VALUE, 1) + 1;
    }


	// 最终调用Unsafe中的方法
	 public final int getAndAddInt(Object obj, long offset, int increment) {
        // value 当前值
         int value;
        do {
            // 根据偏移量获取当前值
            value = this.getIntVolatile(obj, offset);
            // while循环判断当前值与预期值是否一致,一致的话将新值替换给内存中的值
        } while(!this.compareAndSwapInt(obj, offset, value, value + increment));
		// 返回增加前的值
        return value;
    }

其他常用的API与之类似,核心都是调用Unsafe中的native方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值