第7章 Java中的13个原子操作类
线程不安全的更新操作,通常会使用synchronized来解决问题 从JDK 1.5开始提供了java.util.concurrent.atomic包,这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式 Atomic包里一共提供了13个类,属于4种类型的原子更新方式,分别是原子更新基本类型、原子更新数组、原子更新引用和原子更新属性(字段) Atomic包里的类基本都是使用Unsafe实现的包装类
7.1 原子更新基本类型类
使用原子的方式更新基本类型,Atomic包提供了3个类
AtomicBoolean:原子更新布尔类型 AtomicInteger:原子更新整型 AtomicLong:原子更新长整型 以AtomicInteger为例,AtomicInteger的常用方法
int addAndGet(int delta)
boolean compareAndSet(int expect,int update)
int getAndIncrement ( )
void lazySet(int newValue)
int getAndSet(int newValue)
public final int getAndIncrement ( ) {
for ( ; ; ) {
int current = get ( ) ;
int next = current + 1 ;
if ( compareAndSet ( current, next) )
return current;
}
}
public final boolean compareAndSet ( int expect, int update) {
return unsafe. compareAndSwapInt ( this , valueOffset, expect, update) ;
}
for循环体的第一步先取得AtomicInteger里存储的数值 第二步对AtomicInteger的当前数值进行加1操作 第三步调用compareAndSet()方法来进行原子更新操作,该方法先检查当前数值是否等于current
AtomicInteger的值没有被其他线程修改过,则将AtomicInteger的当前数值更新成next的值 如果不等,compareAndSet()方法会返回false,程序会进入for循环重新进行compareAndSet操作
public final native boolean compareAndSwapObject ( Object o, long offset, Object expected, Object x) ;
public final native boolean compareAndSwapInt ( Object o, long offset, int expected, int x) ;
public final native boolean compareAndSwapLong ( Object o, long offset, long expected, long x) ;
Atomic包的类基本都是使用Unsafe实现 通过AtomicBoolean源码可得知,先把Boolean类型转换成整型,再使用用compareAndSwapInt进行CAS 原子更新char、float和double变量也可以用类似的思路
7.2 原子更新数组
使用原子的方式更新数组里的元素,Atomic包提供了3个类
AtomicIntegerArray:原子更新整型数组里的元素 AtomicLongArray:原子更新长整型数组里的元素 AtomicReferenceArray:原子更新引用类型数组里的元素 以AtomicIntegerArray为例,AtomicIntegerArray类主要是提供原子的方式更新数组里的整型,AtomicIntegerArray类的常用方法
int addAndGet(int i,int delta)
boolean compareAndSet(int i,int expect,int update)
注意
数组通过构造方法传递进去,然后AtomicIntegerArray会将当前数组复制一份 当AtomicIntegerArray对内部的数组元素进行修改时,不会影响传入的数组
7.3 原子更新引用类型
使用原子的方式更新引用类型,Atomic包提供了3个类
AtomicReference:原子更新引用类型 AtomicReferenceFieldUpdater:原子更新引用类型里的字段 AtomicMarkableReference:原子更新带有标记位的引用类型
可以原子更新一个布尔类型的标记位和引用类型 构造方法是AtomicMarkableReference(V initialRef,boolean initialMark)
7.4 原子更新字段类
使用原子的方式更新字段类,Atomic包提供了3个类
AtomicIntegerFieldUpdater:原子更新整型的字段的更新器 AtomicLongFieldUpdater:原子更新长整型字段的更新器 AtomicStampedReference:原子更新带有版本号的引用类型
该类将整数值与引用关联起 来,可用于原子的更新数据和数据的版本号,可以解决使用CAS进行原子更新时可能出现的 ABA问题 原子的更新字段类需要两步
原子更新字段类是抽象类,必须使用静态方法newUpdater()创建一个更新器,并设置想要更新的类和属性 更新类的字段(属性)必须被public volatile修饰符
《Java并发编程艺术》
方腾飞 魏鹏 程晓明 著
机械工业出版社