引言
接下来是原子类序章中我们提到的原子更新字段类,它们是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; } } }
相关推荐
scratch少儿编程逻辑思维游戏源码-上下飞行.zip
kkzhilu_Code-Generate_32152_1745864907745
艺术博客_SpringSpringMVCMybatisShirojQueryBootstrapechartswebuploaderlayui_博客管理图表数据日
scratch少儿编程逻辑思维游戏源码-面具古墓.zip
scratch少儿编程逻辑思维游戏源码-时钟上的冰块.zip
健康监测_Android开发_BLE蓝牙通信_心率数据采集与存储_基于小米手环2的实时心率监测应用_支持后台长时间运行的心率记录工具_可导出SQLite数据库的心率数据分析系统_适
scratch少儿编程逻辑思维游戏源码-梦魇忍者.zip
scratch少儿编程逻辑思维游戏源码-谁建得更高.zip
scratch少儿编程逻辑思维游戏源码-忍者攀登.zip
模拟端 后端 qt前端
数据可视化_Android原生Canvas绘图_3D与非3D柱形图饼图折线图面积图曲线图环形图玫瑰图雷达图散点图气泡图仪表盘刻度盘漏斗图象限图_支持手势缩放滑动交互多图叠加动画效果
scratch少儿编程逻辑思维游戏源码-米克 demo.zip
聚合支付系统/官方个人免签系统/三方支付系统稳定安全高并发 附教程 系统采用FastAdmin框架独立全新开发,安全稳定,系统支持代理、商户、码商等业务逻辑。 针对最近一些JD,TB等业务定制,子账号业务逻辑API 非常详细,方便内置对接! IP白名单 业务逻辑 支持IP白名单,黑名单,全局白名单,全局黑名单,保障系统的安全。 接口验签名 采用支付宝RSA加密接口方式,防止篡改数据,导致对账困难,资金大量损失,无故少钱 对接灵活 全部对接参数灵活操作 风控完善 轮询、交易金额、随机金额、最大金额、最小金额等 测试环境: Nginx+PHP7.0+MySQL5.6 网站运行目录:/public 伪静态设置为:thinkphp规则 数据库信息修改路径:/application/database.php
第一步 package.json 下载这三个包 shelljs :执行 shell命令 ssh2-sftp-client 与服务器建立链接(内部有ssh2) chalk 打印彩色输出 第二步 配置脚本命令 deploy 注意后边加上运行环境 执行deploy命令时内部执行了打包动作 「 "deploy": "node deploy/index.js --prod」 第三步准备服务器密码 账号 部署地址 备份地址等等 参考如下 放到 config.js 中 module.exports = [ { id: 0, nodeEnv: "prod", name: "正式环境", domain: "", host: "ip", port: 端口, username: "用户名", password: "密码", path: "/data/www/paccount",//部署路径 removepath: "/data/www/paccount", //删除路径 }, ]; 第四步 如果需要在服务器执行命令 在部署完成后执行 chmodDir 自行决定
scratch少儿编程逻辑思维游戏源码-恐怖矿井.zip
scratch少儿编程逻辑思维游戏源码-爬墙鸟.zip
scratch少儿编程逻辑思维游戏源码-亮灯.zip
scratch少儿编程逻辑思维游戏源码-神秘的游戏.zip
scratch少儿编程逻辑思维游戏源码-矿猫 V4.zip
scratch少儿编程逻辑思维游戏源码-射击游戏构建.zip