在通过分析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;
}
}
}
}
对上面的代码作出一些解释
- 由于在UnSafe类中的theUnSafe变量是由于private修饰的,因此无法直接获得,只能通过反射的形式获得。
- 在UNSAFE进行cas操作的时候,需要获得属性对应的偏移量,因此在代码的16行进行赋值。
- 为了实现自增操作,将CAS操作放在了代码的16行。