Java并发学习(九)-AtomicIntegerFieldUpdater字段原子更新类
来源:互联网 发布:淘宝网客服中心 编辑:程序博客网 时间:2024/06/05 08:27
前面讲的两个AtomicInteger和AtomicIntegerArray,这两个都是在最初设计编码时候就已经考虑到了需要保证原子性。但是往往有很多情况就是,由于需求的更改,原子性需要在后面加入,类似于我不要求你这整个类操作具有原子性,我只要求你里面一个字段操作具有原子性。没错,concurrent.atomic包下AtomicIntegerFieldUpdater就是这个作用的。
AtomicXXXFieldUpdater主要包括以下几个:AtomicIntegerFieldUpdater
,AtomicLongFieldUpdater
,AtomicReferenceFieldUpdater
。
What is AtomicIntegerFieldUpdater
相信前言部分讲的已经很清晰易懂了,AtomicIntegerFieldUpdater就是用来更新某一个实例对象里面的int属性的。
但是注意,在用法上有规则:
- 字段必须是volatile类型的,在线程之间共享变量时保证立即可见
- 字段的描述类型(修饰符public/protected/default/private)是与调用者与操作对象字段的关系一致。也就是说调用者能够直接操作对象字段,那么就可以反射进行原子操作。
- 对于父类的字段,子类是不能直接操作的,尽管子类可以访问父类的字段。
- 只能是实例变量,不能是类变量,也就是说不能加static关键字。
- 只能是可修改变量,不能使final变量,因为final的语义就是不可修改。
- 对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段,不能修改其包装类型(Integer/Long)。如果要修改包装类型就需要使用AtomicReferenceFieldUpdater。
具体规则可以通过以下测试例子来分析:
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;public class AtomicIntegerFieldUpdaterAnalyzeTest { public static void main(String[] args) { AtomicIntegerFieldUpdaterAnalyzeTest test = new AtomicIntegerFieldUpdaterAnalyzeTest(); test.testValue(); } public AtomicIntegerFieldUpdater<DataDemo> updater(String name) { return AtomicIntegerFieldUpdater.newUpdater(DataDemo.class, name); } public void testValue() { DataDemo data = new DataDemo();// //访问父类的public 变量,报错:java.lang.NoSuchFieldException// System.out.println("fatherVar = "+updater("fatherVar").getAndIncrement(data));// // //访问普通 变量,报错:java.lang.IllegalArgumentException: Must be volatile type// System.out.println("intVar = "+updater("intVar").getAndIncrement(data));// //访问public volatile int 变量,成功// System.out.println("publicVar = "+updater("publicVar").getAndIncrement(data));// // //访问protected volatile int 变量,成功// System.out.println("protectedVar = "+updater("protectedVar").getAndIncrement(data));// // //访问其他类private volatile int变量,失败:java.lang.IllegalAccessException// System.out.println("privateVar = "+updater("privateVar").getAndIncrement(data));// // //访问,static volatile int,失败,只能访问实例对象:java.lang.IllegalArgumentException// System.out.println("staticVar = "+updater("staticVar").getAndIncrement(data));// // //访问integer变量,失败, Must be integer type// System.out.println("integerVar = "+updater("integerVar").getAndIncrement(data));// // //访问long 变量,失败, Must be integer type// System.out.println("longVar = "+updater("longVar").getAndIncrement(data)); //自己在自己函数里面可以访问自己的private变量,所以如果可见,那么可以进行原子性字段更新 data.testPrivate(); }}class Father{ public volatile int fatherVar = 4;}class DataDemo extends Father { public int intVar = 4; public volatile int publicVar = 3; protected volatile int protectedVar = 4; private volatile int privateVar = 5; public volatile static int staticVar = 10; //The field finalVar can be either final or volatile, not both //public final volatile int finalVar = 11; public volatile Integer integerVar = 19; public volatile Long longVar = 18L; public void testPrivate(){ DataDemo data = new DataDemo(); System.out.println(AtomicIntegerFieldUpdater.newUpdater(DataDemo.class, "privateVar").getAndIncrement(data)); }
实现
首先看定义:
/** * 允许一个已经定义的类里面的某一个volatile int型变量的原子更新。 * 注意只能够原子更新里面的某一个int型的变量。 * 思路是通过反射获取变量,为一个updater,然后进行更新。 */public abstract class AtomicIntegerFieldUpdater<T>
AtomicIntegerFieldUpdater是一个抽象类,但是它内部有一个private final类型的默认子类,所以在调用newUpdater的时候,会用模式子类来实现:
/** * 创建一个updater, * tclass:包含类的名称 * fieldName:字段名字 */ @CallerSensitive public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { return new AtomicIntegerFieldUpdaterImpl<U> (tclass, fieldName, Reflection.getCallerClass()); }
而除了这些之外,子类中还有判断对象访问权限,以及判断是否为父类,是否同一个包等方法:
//判断second是否为first的父类private static boolean isAncestor(ClassLoader first, ClassLoader second) ;//判断class1和class2是否在同一个包下private static boolean isSamePackage(Class<?> class1, Class<?> class2)//获得包名private static String getPackageName(Class<?> cls)//判断object是否为当前class的一个子类private final void accessCheck(T obj)
另外就是一些CAS方法,实际上都是调用Unsafe.java中的native方法:
public final boolean compareAndSet(T obj, int expect, int update) { accessCheck(obj); return U.compareAndSwapInt(obj, offset, expect, update); } public final boolean weakCompareAndSet(T obj, int expect, int update) { accessCheck(obj); return U.compareAndSwapInt(obj, offset, expect, update); } public final void set(T obj, int newValue) { accessCheck(obj); U.putIntVolatile(obj, offset, newValue); } public final void lazySet(T obj, int newValue) { accessCheck(obj); U.putOrderedInt(obj, offset, newValue); } public final int get(T obj) { accessCheck(obj); return U.getIntVolatile(obj, offset); } public final int getAndSet(T obj, int newValue) { accessCheck(obj); return U.getAndSetInt(obj, offset, newValue); }
AtomicLongFieldUpdater和AtomicReferenceFieldUpdater
在AtomicLongFieldUpdater类中,由于有些32位系统一次性无法对64位的long进行原子运算,所以为了保证安全,在这些不能一次性进行原子运算的需要区分考虑,利用加synchronized锁来实现:
@CallerSensitive public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { Class<?> caller = Reflection.getCallerClass(); if (AtomicLong.VM_SUPPORTS_LONG_CAS) //直接cas实现 return new CASUpdater<U>(tclass, fieldName, caller); else //带synchronized锁实现 return new LockedUpdater<U>(tclass, fieldName, caller); }
什么意思呢?下面给出几个具体方法:
直接CAS实现:
//直接CAS实现 public final boolean compareAndSet(T obj, long expect, long update) { accessCheck(obj); return U.compareAndSwapLong(obj, offset, expect, update); }
加锁的CAS实现:
//加锁的CAS实现 public final boolean compareAndSet(T obj, long expect, long update) { accessCheck(obj); synchronized (this) { long v = U.getLong(obj, offset); if (v != expect) return false; U.putLong(obj, offset, update); return true; } }
在其他方面, AtomicLongFieldUpdater和AtomicReferenceFieldUpdater实现思想基本一致。
参考资料:
http://blog.csdn.net/u010412719/article/details/52068888
- Java并发学习(九)-AtomicIntegerFieldUpdater字段原子更新类
- Java并发编程札记-(三)JUC原子类-05原子方式更新类的指定volatile字段
- java并发基础(九)--- 原子变量
- 笑谈java并发编程四之AtomicIntegerFieldUpdater介绍
- java并发中的原子操作类
- java Atomic原子更新
- java并发编程学习(四) 原子操作的实现原理
- 高级并发编程学习-atomic包学习(重点介绍AtomicInteger、AtomicIntegerFieldUpdater)
- AtomicIntegerFieldUpdater
- AtomicIntegerFieldUpdater
- java 并发 (1):原子计数器
- java并发2.2-原子性
- java原子操作与并发
- java并发之原子性
- Java 原子操作与并发
- java并发-原子性
- 【Java并发编程】原子变量
- java原子性与并发
- spring注解方式配置mybatis数据源
- 怎样把可调DC-DC变身为数控稳压电源
- 学习设计模式笔记--单例模式
- 傅里叶变换 相位谱 幅度谱
- ContentProvider
- Java并发学习(九)-AtomicIntegerFieldUpdater字段原子更新类
- Oracle DataBase Appliance|Oracle数据库服务器存储一体机
- 离散制造业的数据采集之路
- Spring Cloud Eureka 集群高可用
- 解决RecyclerView.getChildAt(Position)崩溃
- 5.Python
- CodeForces
- 安卓TextView实现跑马灯异常问题解决
- zookeeper集群之初识与linux系统环境搭建(一)