CAS
- CAS (Compare And Swap) 比较和交换
- cas(…,oldValue,newValue)方法必定会有两个参数,
- 若oldValue与内存中的值一致,就设置内存中的值为newValue,并返回true
- 若不致,放弃本次操作,反返回false
- CPU保证cas操作的原子性
- cas操作需结合自旋,实现一直尝试,直到成功。即CAS方法本身不保证一定成功,但你可以选择再次尝试,直到成功为止。
封装Unsafe工具类,提供三个cas方法
package org.aidan;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class UnsafeUtil {
private static Unsafe unsafe = null;
public static Unsafe getUnsafe() {
if (unsafe == null) {
synchronized (UnsafeUtil.class) {
if (unsafe == null) {
try {
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
return unsafe;
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
return unsafe;
}
public static boolean casInt(Object obj, String fileName, int oldValue, int newValue) {
try {
long offset = getOffset(obj, fileName);
return getUnsafe().compareAndSwapInt(obj, offset, oldValue, newValue);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return false;
}
public static boolean casLong(Object obj, String fileName, long oldValue, long newValue) {
try {
long offset = getOffset(obj, fileName);
return getUnsafe().compareAndSwapLong(obj, offset, oldValue, newValue);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return false;
}
public static boolean casObject(Object obj, String fileName, Object oldValue, Object newValue) {
try {
long offset = getOffset(obj, fileName);
return getUnsafe().compareAndSwapObject(obj, offset, oldValue, newValue);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return false;
}
private static long getOffset(Object obj, String fileName) throws NoSuchFieldException {
long offset;
Field field;
if (obj instanceof Class) {
Class clazz = (Class) obj;
field = clazz.getDeclaredField(fileName);
offset = getUnsafe().staticFieldOffset(field);
} else {
field = obj.getClass().getDeclaredField(fileName);
offset = getUnsafe().objectFieldOffset(field);
}
return offset;
}
}