AtomicInteger原理分析

前言

AtomicInteger的本质:自旋锁+CAS原子操作

 

1. 源码分析

public class AtomicInteger extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 6214790243416807050L;

    // setup to use Unsafe.compareAndSwapInt for updates
    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); }
    }

    private volatile int value;

使用Unsafe类,定义偏移量 valueOffset,类加载就初始化。用于原子操作CAS

Unsafe类使Java拥有了像C语言的指针一样操作内存空间的能力,同时也带来了指针的问题。

 

AtomicInteger的本质 int value,私有的

这里要注意使用了volatile修饰,volatile 关键字

1.1 JDK1.7及以前

public final int incrementAndGet() {
    //自旋锁
    for (;;) {
        //获取volatitle修饰的变量,最新的主存值
        int current = get();
        //理论上自增值
        int next = current + 1;        
        if (compareAndSet(current, next))
            return next;
    }
}


public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

1.获取volatitle修饰的变量,最新的主存值

2.value+1作为自增值

3. compare value是否就是主存值,是,set next,return next;否,循环下一次

1.2 JDK1.8及以后

/**
     * Atomically increments by one the current value.
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}

下面看getAndAddInt方法

    public final int getAndAddInt(Object obj, long valueOffset, int delta) {
        int expect;
        //自旋
        do {
            //获取主存的值
            expect = this.getIntVolatile(obj, valueOffset);
        //CAS操作
        } while(!this.compareAndSwapInt(obj, valueOffset, expect, expect + delta));

        //返回旧值
        return expect;
    }

封装了自旋锁 

直接封装unsafe方法中了,保证原子性,unsafe是JDK私有的我们不能调用

2. 优缺点

AtomicInteger的优点

1.乐观锁,性能较强,利用CPU自身的特性保证原子性,即CPU的指令集封装compare and swap两个操作为一个指令来保证原子性。

2.适合读多写少模式

但是缺点明显

1.自旋,消耗CPU性能,所以写的操作较多推荐sync

2.仅适合简单的运算,否则会产生ABA问题,自旋的时候,别的线程可能更改value,然后又改回来,此时需要加版本号解决,JDK提供了AtomicStampedReference和AtomicMarkableReference解决ABA问题,提供基本数据类型和引用数据类型版本号支持

 

 

 

 

  • 4
    点赞
  • 13
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

fenglllle

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值