JUC源码分析3-原子变量-AtomicIntegerFieldUpdater/AtomicLongFieldUpdater/AtomicReferenceFieldUpdater

来源:互联网 发布:苹果游戏制作软件 编辑:程序博客网 时间:2024/06/06 19:14

如果我们系统中已经有某个类的变量定义为volatile了,现在为了保证对这个变量的原子性操作,就可以尝试使用这几个类,举个栗子:

import sun.reflect.Reflection;public class AtomicFieldIncr {    //这里最好是public volatile,不要加final、static    //修饰符最好也不要为protected,private,涉及调用者访问被调用者的access问题    public volatile int idx;        public AtomicFieldIncr(){    }        public int getIdx(){        //0,-1返回Reflection本身        System.out.println(Reflection.getCallerClass(0));        System.out.println(Reflection.getCallerClass(-1));        //1返回自己        System.out.println(Reflection.getCallerClass(1));        //2,空返回调用者        System.out.println(Reflection.getCallerClass(2));        System.out.println(Reflection.getCallerClass());        return this.idx;    }        public void setIdx(int idx){        this.idx = idx;    }}

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;public class AtomicIntegerFieldUpdaterTest {    public static void main(String[] args) {        AtomicFieldIncr atomicFieldIncr = new AtomicFieldIncr();        AtomicIntegerFieldUpdater<AtomicFieldIncr> atomicFieldUpdater = AtomicIntegerFieldUpdater.newUpdater(AtomicFieldIncr.class , "idx");                atomicFieldUpdater.set(atomicFieldIncr, 3);        System.out.println(atomicFieldIncr.getIdx());                atomicFieldUpdater.compareAndSet(atomicFieldIncr, 3, 4);        System.out.println(atomicFieldIncr.getIdx());    }}
结果为:
class sun.reflect.Reflectionclass sun.reflect.Reflectionclass com.nettyrpc.juc.AtomicFieldIncrclass com.nettyrpc.juc.AtomicIntegerFieldUpdaterTestclass com.nettyrpc.juc.AtomicIntegerFieldUpdaterTest3class sun.reflect.Reflectionclass sun.reflect.Reflectionclass com.nettyrpc.juc.AtomicFieldIncrclass com.nettyrpc.juc.AtomicIntegerFieldUpdaterTestclass com.nettyrpc.juc.AtomicIntegerFieldUpdaterTest4

还是以AtomicIntegerFieldUpdater开始,AtomicIntegerFieldUpdater本身为abstract,内部提供static实现AtomicIntegerFieldUpdaterImpl,看下AtomicIntegerFieldUpdater的构造函数:

/**tclass就是被调用类,也就是需要变量原子操作的类fieldName:tclass中volatile变量*/public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {//Reflection.getCallerClass()获取我们的调用类    return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName, Reflection.getCallerClass());}

AtomicIntegerFieldUpdater定义了一些抽象方法,跟普通AtomicInteger一样,没什么多余的方法。

看下AtomicIntegerFieldUpdaterImpl的构造函数:

//被调用类中volatile变量的偏移量private final long offset;//被调用类private final Class<T> tclass;//调用类private final Class cclass;AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName, Class<?> caller) {    Field field = null;    int modifiers = 0;    try {        field = tclass.getDeclaredField(fieldName);        modifiers = field.getModifiers();//校验volatile变量的访问权限//被调用者类中的volatile变量一般定义成public volatile不会有问题,如果是其他需要注意             sun.reflect.misc.ReflectUtil.ensureMemberAccess(            caller, tclass, null, modifiers);        sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);    } catch (Exception ex) {        throw new RuntimeException(ex);    }//检验变量类型跟是否是volatile,获取变量的偏移量    Class fieldt = field.getType();    if (fieldt != int.class)        throw new IllegalArgumentException("Must be integer type");    if (!Modifier.isVolatile(modifiers))        throw new IllegalArgumentException("Must be volatile type");    this.cclass = (Modifier.isProtected(modifiers) &&                   caller != tclass) ? caller : null;    this.tclass = tclass;    offset = unsafe.objectFieldOffset(field);}

最主要的是检查调用者对被调用者的volatile变量的访问权限问题,绝对不要定义成static/final,修饰符的问题还是看权限,具体反射校验代码只找到了openjdk的源码,可以自己跟下过程

http://www.docjar.com/html/api/sun/reflect/Reflection.java.html

http://www.docjar.com/html/api/sun/reflect/misc/ReflectUtil.java.html。


类中对于变量的原子操作,大概流程都一样,先做校验,主要是校验你传入的类是否跟之前保存的被调用的类型一致,然后再调用unsafe的底层操作:

public boolean compareAndSet(T obj, int expect, int update) {    if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);    return unsafe.compareAndSwapInt(obj, offset, expect, update);}private void fullCheck(T obj) {    if (!tclass.isInstance(obj))        throw new ClassCastException();    if (cclass != null)        ensureProtectedAccess(obj);}private void ensureProtectedAccess(T obj) {    if (cclass.isInstance(obj)) {        return;    }    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()        )    );}

AtomicLongFieldUpdater跟AtomicIntegerFieldUpdater不一样的是需要判断底层是否支持long的cas操作。

public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {    Class<?> caller = Reflection.getCallerClass();    if (AtomicLong.VM_SUPPORTS_LONG_CAS)        return new CASUpdater<U>(tclass, fieldName, caller);    else        return new LockedUpdater<U>(tclass, fieldName, caller);}

如果底层支持就跟AtomicIntegerFieldUpdater处理方式一样,如果不支持就在原子操作的时候通过synchronized加锁实现:

public boolean compareAndSet(T obj, long expect, long update) {    if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);    synchronized (this) {        long v = unsafe.getLong(obj, offset);        if (v != expect)            return false;        unsafe.putLong(obj, offset, update);        return true;    }}

AtomicReferenceFieldUpdater因为要保证被调用者类中volatile类型引用的原子操作,所以构造函数中需要传入引用类型的class,其他类同。

/**tclass:被调用者vclass:volatile变量的引用类型*/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());}



1 0
原创粉丝点击