AtomicInteger 源码分析

Table of Contents

环境: jdk8

sun.misc.Unsafe

Unsafe类是单例模式, 主要提供了一些操作内存的方法, 为了安全起见, 只有jdk源码才能使用该类

// Unsafe.java
private Unsafe() {}
private static final Unsafe theUnsafe = new Unsafe();
public static Unsafe getUnsafe() {
    Class<?> caller = Reflection.getCallerClass();
    /* 当调用者类的启动器为null表示源码, 否则抛出异常 */
    if (!VM.isSystemDomainLoader(caller.getClassLoader()))
        throw new SecurityException("Unsafe");
    return theUnsafe;
}

java.util.concurrent.atomic.AtomicInteger

类定义

// AtomicInteger.java
public class AtomicInteger extends Number implements java.io.Serializable {
    // setup to use Unsafe.compareAndSwapInt for updates
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset; /* 缓存变量 value 在内存的位置 */

    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    private volatile int value; /* 保证在不同线程的可见性 */
}

主要方法

// AtomicInger.java
public final int addAndGet(int delta) {
    return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}

// Unsafe.java
public final int getAndAddInt(Object o, long offset, int delta) {
    int v;
    do {
        v = getIntVolatile(o, offset); /* 拿到当前变量的值 */
    } while (!compareAndSwapInt(o, offset, v, v + delta)); /* 不断重试, 直到成功为止 */
    return v;
}

/* native 方法, 原子操作, 仅当值等于 expected 时, 设置值为 x, 成功返回 true */
public final native boolean compareAndSwapInt(Object o, long offset,
                                              int expected,
                                              int x);

public final int get() {
    return value;
}

小结

这个类很简单, 仅仅用了关键字 volatile 和 Unsafe 类, 就实现了一个线程安全的 int 类型.

  • 线程间的可见性: volatile
  • 原子操作: Unsafe.compareAndSwap()

Author: Saul Lawliet

Created: 2022-01-13 Thu 22:47