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
A boolean value that can be updated atomically . |
|
An int value that can be updated atomically . |
|
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值已经被更改,值可见)。
三:原子跟新数组
可以用原子方式更新其元素的 int 数组。 |
|
可以用原子方式更新其元素的 long 数组。 |
|
可以用原子方式更新其元素的对象引用数组。 |
构造函数
AtomicIntegerArray(int length) |
AtomicIntegerArray(int[] array) |
public AtomicIntegerArray(int[] array) {
// Visibility guaranteed by final field guarantees
this.array = array.clone();
}
源代码分析:数组通过构造方法传递进去,然后AtomicIntegerArray会将传入的数组复制一份。所以AtomicIntegerArray对内部的元素进行操作时,不会影响传入的数组。
四:更新引用类型的数据
AtomicMarkableReference 维护带有标记位的对象引用,可以原子方式对其进行更新。 |
|
可以用原子方式更新的对象引用。 |
|
AtomicStampedReference 维护带有整数“标志”的对象引用,可以用原子方式对其进行更新。 |
AtomicReference也实现了compareAndSet方法进行原子操作。
boolean |
compareAndSet(V expect, V update) |
五:原子更新字段类
基于反射的实用工具,可以对指定类的指定 volatile int 字段进行原子更新。 |
|
Reflection-based utility that enables atomic updates to specified volatile long fields of specified classes |
|
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.