AtomicInteger原理分析

看源码

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;

AtomicInteger的本质 int value,私有的

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

在JDK1.7及以前使用Java代码实现的自增

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;否,循环下一次

在JDK1.8及以后

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

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

AtomicInteger的优点

1.乐观锁,性能较强,利用CPU自身的特性保证原子性

2.适合读多写少模式

但是缺点明显

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

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

号外,ThreadPoolExecutor大量引用了CAS特性

猜你喜欢

转载自blog.csdn.net/fenglllle/article/details/81316346
今日推荐