版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Pengjx2014/article/details/82710186
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);
}
}