Atomic Operation Classes in Java

One: Why do you need atomic operation classes?

    When a program updates a variable, if multiple threads update it at the same time, then we may not get the expected value. Usually we use synchronized to solve this problem.

Starting with JDK 1.5, the atomic operations classes in the java.util.concurrent.atomic package provide a simple, efficient, and thread-safe way to update a variable.

    Instances of classes AtomicBoolean , AtomicInteger , AtomicLong  and AtomicReference  each provide access to and updates to individual variables of the corresponding type. Each class also provides appropriate utility methods for that type.


Two: Atomic update of basic data types

AtomicBoolean

A boolean  value that can be updated atomically .

AtomicInteger

An int  value that can be updated atomically .

AtomicLong

A long  value that can be updated atomically .

The following is an example of AtomicInteger :

 int

addAndGet (int delta)   Atomically adds the given value to the current value. 

 boolean

compareAndSet (int expect, int update)   If current value ==  expected value, atomically sets the value to the given update value. 

 int

decrementAndGet ()   atomically decrements the current value by 1. 

 int

get ()   gets the current value. 

 int

getAndAdd (int delta)   Atomically adds the given value to the current value. 

 int

getAndDecrement ()   atomically decrements the current value by 1. 

 int

getAndIncrement ()   atomically increments the current value by 1. 

 int

getAndSet (int newValue)   Atomically sets to the given value and returns the old value. 

 int

incrementAndGet ()   atomically increments the current value by 1. 

 int

intValue ()  returns the specified value   as an int . 

    For these methods: i.addAndGet(1); -> ++i  

                            i. getAndAdd(1);     -> i++

            So how do they implement atomic operations?

   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方法进行原子操作。

boolean

compareAndSet(V expect, V update) 
          如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。

 

五:原子更新字段类

AtomicIntegerFieldUpdater<T>

基于反射的实用工具,可以对指定类的指定 volatile int 字段进行原子更新。

AtomicLongFieldUpdater<T>

Reflection-based utility that enables atomic updates to specified volatile long  fields of specified classes

AtomicReferenceFieldUpdater<T,V>

Reflection-based utility that enables  atomic updates to specified volatile fields of specified classes.

①Atomic update field classes are all abstract classes. Every time you use them, you must use the static method newUpdater() to create an updater, and set the classes and properties you want to update.

② The fields of the update class must use the public volatile modifier.

 

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325401516&siteId=291194637