《Java中AtomicIntegerFieldUpdater的应用》
在J.U.C下的atomic包下有一些用于并发进行原子更新的类。
例如:
1、AtomicInteger/AtomicLong/AtomicBoolean/AtomicReference
是关于对变量的原子更新,
2、AtomicIntegerArray/AtomicLongArray/AtomicReferenceArray
是关于对数组的原子更新
3、AtomicIntegerFieldUpdater<T>/AtomicLongFieldUpdater<T>/AtomicReferenceFieldUpdater<T,V>
是基于反射的原子更新字段的值。
关于AtomicInteger/AtomicIntegerArray都比较简单,如何使用可以查相应的API文档,对于AtomicIntegerFieldUpdater 的使用稍微有一些限制和约束,约束如下:
(1)字段必须是volatile类型的,在线程之间共享变量时保证立即可见.eg:volatile int value = 3
(2)字段的描述类型(修饰符public/protected/default/private)是与调用者与操作对象字段的关系一致。也就是说调用者能够直接操作对象字段,那么就可以反射进行原子操作。但是对于父类的字段,子类是不能直接操作的,尽管子类可以访问父类的字段。
(3)只能是实例变量,不能是类变量,也就是说不能加static关键字。
(4)只能是可修改变量,不能使final变量,因为final的语义就是不可修改。实际上final的语义和volatile是有冲突的,这两个关键字不能同时存在。
(5)对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段,不能修改其包装类型(Integer/Long)。如果要修改包装类型就需要使用AtomicReferenceFieldUpdater。
例子如下:
public class TestAtomicIntegerFieldUpdater {
public static void main(String[] args){
TestAtomicIntegerFieldUpdater tIA = new TestAtomicIntegerFieldUpdater();
tIA.doIt();
}
public AtomicIntegerFieldUpdater<DataDemo> updater(String name){
return AtomicIntegerFieldUpdater.newUpdater(DataDemo.class,name);
}
public void doIt(){
DataDemo data = new DataDemo();
System.out.println("publicVar = "+updater("publicVar").getAndAdd(data, 2));
/*
* 由于在DataDemo类中属性value2/value3,在TestAtomicIntegerFieldUpdater中不能访问
* */
//System.out.println("protectedVar = "+updater("protectedVar").getAndAdd(data,2));
//System.out.println("privateVar = "+updater("privateVar").getAndAdd(data,2));
//System.out.println("staticVar = "+updater("staticVar").getAndIncrement(data));//报java.lang.IllegalArgumentException
/*
* 下面报异常:must be integer
* */
//System.out.println("integerVar = "+updater("integerVar").getAndIncrement(data));
//System.out.println("longVar = "+updater("longVar").getAndIncrement(data));
}
}
class DataDemo{
public volatile int publicVar=3;
protected volatile int protectedVar=4;
private volatile int privateVar=5;
public volatile static int staticVar = 10;
//public final int finalVar = 11;
public volatile Integer integerVar = 19;
public volatile Long longVar = 18L;
}
参考资料
1、http://www.blogjava.net/xylz/archive/2010/07/02/325079.html