手动实现一个原子变量类

47 阅读1分钟

在通过分析AtomicInteger类可以看到主要是由于UnSafe这个类对象在进行CAS底层的原子操作。因此,要手动实现这个原子类变量,我们需要手动利用UnSafe对象进行操作。AtomcInteger的源代码如下

public final boolean compareAndSet(int expectedValue, int newValue) {
    return U.compareAndSetInt(this, VALUE, expectedValue, newValue);
}
public final native boolean compareAndSetInt(Object o, long offset,
                                             int expected,
                                             int x);

首先进行几个变量参数以及应该处于的“位置”进行分析,手动实现的原子类必须要有UnSafe操作对象,且这个对象应该属于类,因为我们不需要每创建一个对象就要有一个新的UnSafe,同理需要一个类对象所属的OFFSET。以及一个由volatile修饰的局部变量value。

class MyAtomicInteger0 {
    private static Unsafe UNSAFE;
    private static Long OFFSET;

    private volatile int value;

    public MyAtomicInteger0(int value) {
        this.value = value;
    }

    static {
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            UNSAFE = (Unsafe) theUnsafe.get(null);
            OFFSET = UNSAFE.objectFieldOffset(MyAtomicInteger0.class.getDeclaredField("value"));
        } catch (NoSuchFieldException  | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public int getValue() {
        return value;
    }

    public void increment() {
        while (true) {
            int pre = getValue();
            if (UNSAFE.compareAndSwapInt(this,OFFSET,pre,pre+1)) {
                break;
            }

        }

    }
}

对上面的代码作出一些解释

  1. 由于在UnSafe类中的theUnSafe变量是由于private修饰的,因此无法直接获得,只能通过反射的形式获得。
  2. 在UNSAFE进行cas操作的时候,需要获得属性对应的偏移量,因此在代码的16行进行赋值。
  3. 为了实现自增操作,将CAS操作放在了代码的16行。