Java源码解析AtomicInteger实现原理

Java中的AtomicInteger是原子整数,它可以用在多线程环境下,并且不会造成数据不一致的问题。

首先看一下AtomicInteger的javadoc注释。

An int value that may be updated atomically. 
See the java.util.concurrent.atomic package specification 
for description of the properties of atomic variables. 
An AtomicInteger is used in applications such as 
atomically incremented counters, 
and cannot be used as a replacement for an Integer.
 However, this class does extend Number to 
allow uniform access by tools and utilities that 
deal with numerically-based classes.

在javadoc注释中讲到,AtomicInteger是一个可以原子更新的整形数值。AtomicInteger可以用在作为原子自增的计数器类似的应用中,但是不能作为Integer的替代。

首先看一下成员变量。

// 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使用了Unsafe类来执行CAS操作。CAS是compare and swap的缩写,它是在计算中很常用的策略。计算机指令提供了CAS操作原语,提供原子操作。value保存实际的整数值。它被volatile修饰,来保证多线程间的可见性。在静态代码块中,通过unsafe的方法,获取到value属性在内存中的地址,并保存在valueOffset中。

接下来看一下构造函数。

/**
     * Creates a new AtomicInteger with the given initial value.
     *
     * @param initialValue the initial value
     */
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

    /**
     * Creates a new AtomicInteger with initial value {@code 0}.
     */
    public AtomicInteger() {
    }

该类提供了2个构造函数,比较简单,不再展开。

接下来是普通的get和set函数。如下。

/**
     * Gets the current value.
     *
     * @return the current value
     */
    public final int get() {
        return value;
    }

    /**
     * Sets to the given value.
     *
     * @param newValue the new value
     */
    public final void set(int newValue) {
        value = newValue;
    }

 

get和set函数也没有什么特殊之处。再接下来是lazySet,如下图。

    /**
     * Eventually sets to the given value.
     *
     * @param newValue the new value
     * @since 1.6
     */
    public final void lazySet(int newValue) {
        unsafe.putOrderedInt(this, valueOffset, newValue);
    }

从注释中我们可以看到,最终会设置为给定的值。也就是说,当有多个线程同时调用lazySet时,会根据线程的调用顺序进行排队,依次设置各个线程调用该函数时传递的参数。

接下来是getAndSet函数。它的作用是原子的设置为新值,并返回旧值。从代码可以看出,它直接调用unsafe的getAndSetInt函数来实现。我们看一下getAndSet的源码,它里面是一个do-while结构,每次先获取int值的最新值,然后执行compareAndSwapInt函数,将int值设置为新的value值。如果失败,那么再重新获取int的值,继续同样的操作,直到成功。当线程1获取了旧的int值之后,如果有线程2得到执行,将int值设置为了新的newValue2,那么当线程1再执行compareAndSwapInt函数时,就会返回false;也正是通过compareAndSwapInt函数,来保证了对值的修改的原子性。

    /**
     * Atomically sets to the given value and returns the old value.
     *
     * @param newValue the new value
     * @return the previous value
     */
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }
    public final int getAndSetInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var4));

        return var5;
    }

接下来是compareAndSet函数,它的作用是,当int当前值与期望值相等时,那么原子性的将int值设置为给定的更新的值。该函数也是直接调用了compareAndSwapInt函数进行实现。

    /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

AtomicInteger类中还有其他一些函数,不太常用,这里就不一一详述了。

你可能感兴趣的:(Java源码解析)