您的位置:首页 > 编程语言 > Java开发

Java中的原子操作类

2018-03-30 13:35 120 查看
一:为什么需原子操作类
    当程序更新一个变量时,如果多个线程同时更新,那么我们可能得不到期望值。通常我们使用synchronized解决这个问题。
从JDK1.5开始,在java.util.concurrent.atomic 包的原子操作类提供了一种用法简单、高效、线程安全地更新一个变量的方式。
    类 AtomicBooleanAtomicIntegerAtomicLong 和 AtomicReference 的实例各自提供对相应类型单个变量的访问和更新。每个类也为该类型提供适当的实用工具方法。

二:原子更新基本数据类型
AtomicBoolean
可以用原子方式更新的 boolean 值。
AtomicInteger
可以用原子方式更新的 int 值。
AtomicLong
可以用原子方式更新的 long 值。
下面以AtomicInteger为例:
 intaddAndGet(int delta) 
  以原子方式将给定值与当前值相加。
 booleancompareAndSet(int expect, int update) 
  如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
 intdecrementAndGet() 
  以原子方式将当前值减 1。
 intget() 
  获取当前值。
 intgetAndAdd(int delta) 
  以原子方式将给定值与当前值相加。
 intgetAndDecrement() 
  以原子方式将当前值减 1。
 intgetAndIncrement() 
  以原子方式将当前值加 1。
 intgetAndSet(int newValue) 
  以原子方式设置为给定值,并返回旧值。
 intincrementAndGet() 
  以原子方式将当前值加 1。
 intintValue() 
  以 int 形式返回指定的数值。
    对于这些方法:i. addAndGet(1);    ->  ++i  
                            i. getAndAdd(1);     -> i++
            那么它们是如何实现原子操作的? public final boolean compareAndSet(int expect, int update) {

return unsafe.compareAndSwapInt(this, valueOffset, expect, update);

}
        因为compareAndSwapInt的源码无法追到,我们采用分析的方式来解释CAS算法的逻辑。
    多线程并发的情况下,如果this值与expect值相等,则将update值赋值给this,更新成功返回true。若this值与expect值不相等,则说另一个线程已经访问并修改了值,则返回false,说明更新失败。
            代码没有加锁,那么另一个线程是如何得知值已经被修改了?       private volatile int value;        volatile修饰的变量,多线程间可见。一个线程修改了value值,其它正在访问value的线程也得到通知(value值已经被更改,值可见)。
 
三:原子跟新数组
AtomicIntegerArray
可以用原子方式更新其元素的 int 数组。
AtomicLongArray
可以用原子方式更新其元素的 long 数组。
AtomicReferenceArray<E>
可以用原子方式更新其元素的对象引用数组。
AtomicIntegerArray为例
构造函数
AtomicIntegerArray(int length) 
  创建给定长度的新 AtomicIntegerArray。
AtomicIntegerArray(int[] array) 
  创建与给定数组具有相同长度的新 AtomicIntegerArray,并从给定数组复制其所有元素。
public AtomicIntegerArray(int[] array) {

// Visibility guaranteed by final field guarantees

this.array = array.clone();

}

源代码分析:数组通过构造方法传递进去,然后AtomicIntegerArray会将传入的数组复制一份。所以AtomicIntegerArray对内部的元素进行操作时,不会影响传入的数组。

四:更新引用类型的数据
AtomicMarkableReference<V>
AtomicMarkableReference 维护带有标记位的对象引用,可以原子方式对其进行更新。
AtomicReference<V>
可以用原子方式更新的对象引用。
AtomicStampedReference<V>
AtomicStampedReference 维护带有整数“标志”的对象引用,可以用原子方式对其进行更新。
    AtomicReference也实现了compareAndSet方法进行原子操作。
booleancompareAndSet(V expect, V update) 
          如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
 
五:原子更新字段类
AtomicIntegerFieldUpdater<T>
基于反射的实用工具,可以对指定类的指定 volatile int 字段进行原子更新。
AtomicLongFieldUpdater<T>
基于反射的实用工具,可以对指定类的指定 volatile long 字段进行原子更新
AtomicReferenceFieldUpdater<T,V>
基于反射的实用工具,可以对指定类的指定 volatile 字段进行原子更新。
①原子更新字段类都是抽象类,每次使用都必须使用静态方法newUpdater()创建一个更新器,并且设置想要更新的类和属性。
②更新类的字段必须使用public volatile修饰符。
 
 
 
 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  原子操作类