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
- JUC源码分析3-原子变量-AtomicIntegerFieldUpdater/AtomicLongFieldUpdater/AtomicReferenceFieldUpdater
- JUC源码分析1-原子变量-AtomicInteger/AtomicBoolean/AtomicLong/AtomicReference
- JUC源码分析2-原子变量-AtomicIntegerArray/AtomicLongArray/AtomicReferenceArray
- JUC源码分析4-原子变量-AtomicStampedReference/AtomicMarkableReference
- JUC - Semaphore 源码分析
- JUC - CountDownLatch 源码分析
- JUC - ReentrantLock 源码分析
- JUC - Condition 源码分析
- JUC - ReentrantReadWriteLock 源码分析
- JUC - ThreadPoolExecutor 源码分析
- JUC - FutureTask 源码分析
- java原子更新器AtomicReferenceFieldUpdater的使用
- java原子更新器AtomicReferenceFieldUpdater的使用
- JUC - AbstractQueuedSynchronizer(AQS) 源码分析
- 源码分析之JUC-Exchanger
- Java多线程 -- JUC包源码分析3-- volatile/final语义
- Java多线程 -- JUC包源码分析3-- volatile/final语义
- AtomicIntegerFieldUpdater
- rxJava 学习之路(二)
- SqlBulkCopy 数据库批量插入数据
- poj2287田忌赛马
- python 的日志logging模块学习
- 月薪2w的程序员技能
- JUC源码分析3-原子变量-AtomicIntegerFieldUpdater/AtomicLongFieldUpdater/AtomicReferenceFieldUpdater
- UIView的setNeedsLayout, layoutIfNeeded 和 layoutSubviews 方法之间的关系解释
- 整理标签
- QT 文件管理
- volley分析总结
- JDBC笔记-基本操作
- web.xml配置文件介绍
- MyEclipse 中各种 libraries 的含义
- ajax在ie上不能用了