AtomicReferenceFieldUpdater原始碼閱讀筆記
阿新 • • 發佈:2019-01-02
AtomicReferenceFieldUpdater使用
AtomicReferenceFieldUpdater的作用就是原子更新類中被volatile修飾的欄位,具體使用如下:
class Person {
volatile String name = "lx";
}
public class ReferenceFieldUpdaterTest {
public static void main(String[] args) {
AtomicReferenceFieldUpdater updater = AtomicReferenceFieldUpdater.newUpdater(Person.class, String.class, "name" );
Person person = new Person();
updater.compareAndSet(person, person.name, "Kylin");
System.out.println("------->" + person.name);
}
}
輸出結果如下:
------->Kylin
AtomicReferenceFieldUpdater原始碼分析
AtomicReferenceFieldUpdater定義了一組抽象方法和工廠構造器如下:
//定義工廠方法,構建AtomicReferenceFieldUpdater
public static <U,W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass,
Class<W> vclass,
String fieldName) {
return new AtomicReferenceFieldUpdaterImpl<U,W>
(tclass, vclass, fieldName, Reflection.getCallerClass());
}
//預設構造方法
protected AtomicReferenceFieldUpdater() {}
//cas更新指定欄位
public abstract boolean compareAndSet(T obj, V expect, V update);
public abstract boolean weakCompareAndSet(T obj, V expect, V update);
public abstract void set(T obj, V newValue);
public abstract void lazySet(T obj, V newValue);
public abstract V get(T obj);
public V getAndSet(T obj, V newValue) {
V prev;
do {
prev = get(obj);
} while (!compareAndSet(obj, prev, newValue));
return prev;
}
public final V getAndUpdate(T obj, UnaryOperator<V> updateFunction) {
V prev, next;
do {
prev = get(obj);
next = updateFunction.apply(prev);
} while (!compareAndSet(obj, prev, next));
return prev;
}
public final V updateAndGet(T obj, UnaryOperator<V> updateFunction) {
V prev, next;
do {
prev = get(obj);
next = updateFunction.apply(prev);
} while (!compareAndSet(obj, prev, next));
return next;
}
public final V getAndAccumulate(T obj, V x,
BinaryOperator<V> accumulatorFunction) {
V prev, next;
do {
prev = get(obj);
next = accumulatorFunction.apply(prev, x);
} while (!compareAndSet(obj, prev, next));
return prev;
}
public final V accumulateAndGet(T obj, V x,
BinaryOperator<V> accumulatorFunction) {
V prev, next;
do {
prev = get(obj);
next = accumulatorFunction.apply(prev, x);
} while (!compareAndSet(obj, prev, next));
return next;
}
內部類實現如下,程式碼整體較簡單,注重看下構造器中的一個小細節,Class被ClassLoader載入,所有的ClassLoader應該在一個雙親委託模型的ClassLoader載入鏈中。tclass和vclass的類載入器會判斷是否在一個類載入器鏈中。
private static final class AtomicReferenceFieldUpdaterImpl<T,V>
extends AtomicReferenceFieldUpdater<T,V> {
//使用Unsafe做CAS操作
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private final long offset;
/**
* 待更新的的物件的類的Class物件
*/
private final Class<?> cclass;
/** 待操作的目標物件 */
private final Class<T> tclass;
/** 待操作的欄位的型別 */
private final Class<V> vclass;
/** 建立原子更新器 */
AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,
final Class<V> vclass,
final String fieldName,
final Class<?> caller) {
final Field field;
final Class<?> fieldClass;
final int modifiers;
try {
//獲取tclass的Field
field = AccessController.doPrivileged(
new PrivilegedExceptionAction<Field>() {
public Field run() throws NoSuchFieldException {
return tclass.getDeclaredField(fieldName);
}
});
modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers);
ClassLoader cl = tclass.getClassLoader();
ClassLoader ccl = caller.getClassLoader();
//判斷class和修改的欄位的類載入器是否在一個類載入器委託鏈中
if ((ccl != null) && (ccl != cl) &&
((cl == null) || !isAncestor(cl, ccl))) {
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
}
fieldClass = field.getType();
} catch (PrivilegedActionException pae) {
throw new RuntimeException(pae.getException());
} catch (Exception ex) {
throw new RuntimeException(ex);
}
if (vclass != fieldClass)
throw new ClassCastException();
if (vclass.isPrimitive())
throw new IllegalArgumentException("Must be reference type");
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
this.cclass = (Modifier.isProtected(modifiers) &&
tclass.isAssignableFrom(caller) &&
!isSamePackage(tclass, caller))
? caller : tclass;
this.tclass = tclass;
this.vclass = vclass;
this.offset = U.objectFieldOffset(field);
}
//判斷第二個類載入器是否能在第一個載入器委託鏈中找到
private static boolean isAncestor(ClassLoader first, ClassLoader second) {
ClassLoader acl = first;
do {
acl = acl.getParent();
if (second == acl) {
return true;
}
} while (acl != null);
return false;
}
//判斷兩個classes是否是相同的類載入器和包修飾
private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
return class1.getClassLoader() == class2.getClassLoader()
&& Objects.equals(getPackageName(class1), getPackageName(class2));
}
private static String getPackageName(Class<?> cls) {
String cn = cls.getName();
int dot = cn.lastIndexOf('.');
return (dot != -1) ? cn.substring(0, dot) : "";
}
//判斷目標引數是否obj的例項
private final void accessCheck(T obj) {
if (!cclass.isInstance(obj))
throwAccessCheckException(obj);
}
private final void throwAccessCheckException(T obj) {
if (cclass == tclass)
throw new ClassCastException();
else
throw new RuntimeException(
new IllegalAccessException(
"Class " +
cclass.getName() +
" can not access a protected member of class " +
tclass.getName() +
" using an instance of " +
obj.getClass().getName()));
}
private final void valueCheck(V v) {
if (v != null && !(vclass.isInstance(v)))
throwCCE();
}
static void throwCCE() {
throw new ClassCastException();
}
//原子更新
public final boolean compareAndSet(T obj, V expect, V update) {
accessCheck(obj);
valueCheck(update);
return U.compareAndSwapObject(obj, offset, expect, update);
}
public final boolean weakCompareAndSet(T obj, V expect, V update) {
// same implementation as strong form for now
accessCheck(obj);
valueCheck(update);
return U.compareAndSwapObject(obj, offset, expect, update);
}
public final void set(T obj, V newValue) {
accessCheck(obj);
valueCheck(newValue);
U.putObjectVolatile(obj, offset, newValue);
}
public final void lazySet(T obj, V newValue) {
accessCheck(obj);
valueCheck(newValue);
U.putOrderedObject(obj, offset, newValue);
}
@SuppressWarnings("unchecked")
public final V get(T obj) {
accessCheck(obj);
return (V)U.getObjectVolatile(obj, offset);
}
@SuppressWarnings("unchecked")
public final V getAndSet(T obj, V newValue) {
accessCheck(obj);
valueCheck(newValue);
return (V)U.getAndSetObject(obj, offset, newValue);
}
}