引言
接下来是原子类序章中我们提到的原子更新字段类,它们是AtomicLongFieldUpdater,AtomicIntegerFieldUpdater,AtomicReferenceFieldUpdater。其实就是了原子的更新一个引用类型的整形字段、long型字段、引用类型字段。
AtomicIntegerFieldUpdater
首先根据如下的类结构可见,它本身是一个抽象方法,提供了一个静态工厂方法newUpdater()来生成实例。
public abstract class AtomicIntegerFieldUpdater<T> { @CallerSensitive public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { return new AtomicIntegerFieldUpdaterImpl<U> (tclass, fieldName, Reflection.getCallerClass()); } /** * Protected do-nothing constructor for use by subclasses. */ protected AtomicIntegerFieldUpdater() { } .....
接着来看它的实现类,它的实现类AtomicIntegerFieldUpdaterImpl是它的一个私有静态内部类:
private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> { private static final Unsafe unsafe = Unsafe.getUnsafe(); private final long offset; private final Class<T> tclass; private final Class<?> cclass; AtomicIntegerFieldUpdaterImpl(final Class<T> tclass, final String fieldName, final Class<?> caller) { final Field field; final int modifiers; try { 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(); if ((ccl != null) && (ccl != cl) && ((cl == null) || !isAncestor(cl, ccl))) { sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); } } catch (PrivilegedActionException pae) { throw new RuntimeException(pae.getException()); } catch (Exception ex) { throw new RuntimeException(ex); } 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); } .....
从它的实例构造方法可见,它首先会对目标class及其指定的字段进行检测,主要是访问权限、数据类型是否是int,是否 是volatile修饰,最后当然还有通过unsafe获取目标字段的偏移量,为后面的CAS原子操作作准备。
从以上方法我们可以得出,要想使用AtomicIntegerFieldUpdater原子的更新一个对象的某个字段,必须满足以下条件:
- 调用者必须有对目标类的访问权限;
- 目标字段必须是整形int或者Integer;
- 目标字段必须是public修饰的;
- 目标字段必须是volatile修饰的。
另外,实现类AtomicIntegerFieldUpdaterImpl还实现了一些AtomicIntegerFieldUpdater的基础的原子更新的抽象方法:
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); } public boolean weakCompareAndSet(T obj, int expect, int update) { if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); return unsafe.compareAndSwapInt(obj, offset, expect, update); } public void set(T obj, int newValue) { if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); unsafe.putIntVolatile(obj, offset, newValue); } public void lazySet(T obj, int newValue) { if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); unsafe.putOrderedInt(obj, offset, newValue); } public final int get(T obj) { if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); return unsafe.getIntVolatile(obj, offset); } public int getAndSet(T obj, int newValue) { if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); return unsafe.getAndSetInt(obj, offset, newValue); } public int getAndIncrement(T obj) { return getAndAdd(obj, 1); } public int getAndDecrement(T obj) { return getAndAdd(obj, -1); } public int getAndAdd(T obj, int delta) { if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); return unsafe.getAndAddInt(obj, offset, delta); } public int incrementAndGet(T obj) { return getAndAdd(obj, 1) + 1; } public int decrementAndGet(T obj) { return getAndAdd(obj, -1) - 1; } public int addAndGet(T obj, int delta) { return getAndAdd(obj, delta) + delta; }
这些方法和AtomicInteger提供的方法一致,不再熬述。剩下的其他的一些方法和AtomicInteger提供的原子更新方法几乎一样,都分为那四大原子更新方法,也不在一一列举。
AtomicLongFieldUpdater
再看AtomicLongFieldUpdater,它和AtomicIntegerFieldUpdater的结构基本一致,也是一个抽象方法,不同的是它是对long型字段的原子更新,而不是整形。
另外还有一个比较重要的区别就是,它的实现类有两个,根据平台是否支持8字节的CAS操作来选择不同的实现:
@CallerSensitive 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); }
如果平台支持8字节的CAS操作,那么实现逻辑 CASUpdater就和AtomicIntegerFieldUpdater中的实现类似,也就是直接使用CAS操作达到原子操作的目的,如果平台不支持8字节的CAS操作,那么就使用内部加锁的方式实现对8字节的原子更新操作,如下所示为当平台不支持8字节的CAS操作时的内部加锁实现方式:
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; } } public boolean weakCompareAndSet(T obj, long expect, long update) { return compareAndSet(obj, expect, update); } public void set(T obj, long newValue) { if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); synchronized (this) { unsafe.putLong(obj, offset, newValue); } } public void lazySet(T obj, long newValue) { set(obj, newValue); } public long get(T obj) { if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); synchronized (this) { return unsafe.getLong(obj, offset); } }
可见当不支持8字节的CAS操作时,JDK8采用的是synchronized锁实现。
AtomicLongFieldUpdater和AtomicIntegerFieldUpdater一样,可以对所操作的字段进行加减和更复杂的函数式运算,具体方法和AtomicLong类似,不再一一列举了。
AtomicReferenceFieldUpdater
最后再看AtomicReferenceFieldUpdater,它同样是一个抽象类,也是通过一个工厂方法生成原子更新器实例,同样它的实现方法也是通过CAS实现,所要操作的字段也必须是特定类型的public volatile修饰的。
AtomicReferenceFieldUpdater比 AtomicReference的原子更新操作更细粒度和更精确,它比AtomicReference这种直接更新整个对象要高效的多。
测试代码:
public class AtomicIntegerFieldUpdaterTest { private static AtomicIntegerFieldUpdater<User> a = AtomicIntegerFieldUpdater .newUpdater(User.class, "old"); public static void main(String[] args) { User user = new User("conan", 10); System.out.println(a.getAndIncrement(user)); //10 System.out.println(a.get(user)); //11 } public static class User { private String name; public volatile int old; public User(String name, int old) { this.name = name; this.old = old; } public String getName() { return name; } public int getOld() { return old; } } }
相关推荐
原子指令是特殊的硬件指令,以不可分的方式对一个或多个内存位置执行操作。无论其他处理器执行什么指令...但是,由于它们是低层的,并且只能对数据结构进行小的更新,因此使用它们来实现并行数据结构是一项艰巨的任务。
也就是说调用者能够直接操作对象字段 ,那么就可以反射进行原子操作。 对于父类的字段,子类是不能直接操作的,尽管子类可以访问父类的字段。 只能是实例变量,不能是类变量,也就是说不能加static关键字。 ...
本程序能够将你计算机的时钟与美国NIST原子时钟进行同步,显示本机时间及原子钟时间,显示时间误差,如果有时间误差,点击一下校准即可进行时间同步,非常方便。本程序在时间校准时需要连接到互联网,因为同步时间...
同步练习 1.1 原子结构.doc
同步之原子操作.pptx
原子物理,核物理,理念原创 哲学指导科学思维 洞察宇宙之深层奥秘 必从最简单的理论开始 勇于开拓创新
原子结构同步练习.doc
此外讨论一个数据结构必须同时讨论在该类数据上执行的运算才有意义。 在许多类型的程序的设计中,数据结构的选择是一个基本的设计考虑因素。许多大型系统的构造经验表明,系统实现的困难程度和系统构造的质量都严重...
数据类型可分为两类:一类是非结构的原子类型,如C#语言中的基本类型 (整型、实型、字符型等);另一类是结构类型,它的成分可以由多个结构类型 组成,并可以分解。结构类型的成分可以是非结构的,也可以是结构的。...
诸如d嵌段过渡金属的原子摩尔体积收缩或镧系金属的Eu和Yb原子体积异常之类的细节,除了原子的电子结构之外,还与核反应。 原子的原子核在恒星内部被合成,并且只有在迁移到恒星的外围之后才捕获电子,成为稳定的...
九年级化学上册同步教学课题2原子的结构共39张PPT学习教案.pptx
原子操作 四种原子更新方式文档,分别是原子更新基本类型,原子更 新数组,原子更新引用和原子更新字段。Atomic包里的类基本都是使用Unsafe实现的包装 类
高中原子结构教案
高中化学人教版必修2同步练习 第1章 物质结构 元素周期律 第1节 第2课时 元素的性质和原子结构.doc
高一化学同步测试—原子结构[精选].doc
2018年秋九年级化学上册第1节构成物质的基本微粒3.1.3原子结构相对原子质量同步练习沪教版
【高中新课标同步用书】高中物理 第十八章原子结构 2原子的核式结构模型(pdf)新人教版选修3-5
原子结构与性质原子结构与元素的性质PPT课件.pptx
很好用的原子钟同步软件,服务器出现时钟同步异常可以使用该软件
使用C语言实现数据结构 表,原子,链表,栈,集合,动态数组,环,序列,位向量,线程,异常,精度计算,内存管理,字符串 包含了不透明指针,断言处理时机,二级指针的用法,宏定义,复杂结构体,setjmp/longjmp,...