1.无锁的原子类实现原理
1.1.CAS原理
原子类的无锁操作的实现很简单,那就是硬件支持,就是CPU提供的CAS指令(全称:Compare And Swap,即"比较-交换")。
CAS指令包含三个部分:
- 变量的内存地址A(当前值,curValue)
- 用于比较的值B(老值,expect)
- 共享变量的新值C(新值,newValue)
当前只有当内存地址A处的值等于B值时,才能够将内存地址A处的值更新为新值C。
作为一条CPU指令,CAS指令本身是能够保证原子性的
CAS的Java代码实现如下:
只有当目前 count 的值和期望值 expect 相等时,才会将 count 更新为 newValue。
class SimulatedCAS{
int count;
synchronized int cas(
int expect, int newValue){
// 读目前 count 的值
int curValue = count;
// 比较目前 count 值是否 == 期望值
if(curValue == expect){
// 如果是,则更新 count 的值
count = newValue;
}
// 返回写入前的值
return curValue;
}
}
1.2.CAS自旋
CAS自旋:其实就是循环尝试。就是说当前线程经过CAS比较发现expectVal与NowVal不符,代表数据已经被修改过了,此时就再次尝试读取新值计算,并再次CAS。代码如下:
class SimulatedCAS{
volatile int count;
// 实现 count+=1
addOne(){
do {
newValue = count+1; //①
}while(count !=
cas(count,newValue) //②
}
// 模拟实现 CAS,仅用来帮助理解
synchronized int cas(
int expect, int newValue){
// 读目前 count 的值
int curValue = count;
// 比较目前 count 值是否 == 期望值
if(curValue == expect){
// 如果是,则更新 count 的值
count= newValue;
}
// 返回写入前的值
return curValue;
}
}
1.3.Java原子类如何通过CAS实现原子自增
这里以AtomicLong 的getAndIncrement()举例,其方法内部就是基于CAS实现,代码如下,其中this和valueoffset可以唯一确定共享变量的地址A:
final long getAndIncrement() {
return unsafe.getAndAddLong(
this, valueOffset, 1L);
}
unsafe.getAndAddLong() 方法的源码如下:
public final long getAndAddLong(
Object o, long offset, long delta){
long v;
do {
// 读取内存中的值
v = getLongVolatile(o, offset);
} while (!compareAndSwapLong(
o, offset, v, v + delta));
return v;
}
// 原子性地将变量更新为 x
// 条件是内存中的值等于 expected
// 更新成功则返回 true
native boolean compareAndSwapLong(
Object o, long offset,
long expected,
long x);
由源码可以看出,CAS的方法都是由上述的三个部分组成,成员变量地址A(当前值),期望值B,新值C
2.原子类概述
原子类可以大概划分为如下五个类别:
- 原子化的基本数据类型
- 原子化的对象的引用类型
- 原子化数组
- 原子化对象属性更新器
- 原子化的累加器

2.1.原子化的基本数据类型
其中包括:AtomicBoolean、AtomicInteger 和 AtomicLong等
2.2.原子化的对象引用类型
其中包括:AtomicReference、AtomicStampedReference 和 AtomicMarkableReference,利用它们可以实现对象引用的原子化更新
AtomicStampedReference 和 AtomicMarkableReference 这两个原子类可以解决 ABA 问题
2.3.原子化数组
相关实现有 AtomicIntegerArray、AtomicLongArray 和 AtomicReferenceArray,利用这些原子类,我们可以原子化地更新数组里面的每一个元素
2.4.原子化对象属性更新器
相关实现有 AtomicIntegerFieldUpdater、AtomicLongFieldUpdater 和 AtomicReferenceFieldUpdater,利用它们可以原子化地更新对象的属性,这三个方法都是利用反射机制实现的,创建更新器的方法如下:
创建更新器的方法如下:
public static <U>
AtomicXXXFieldUpdater<U>
newUpdater(Class<U> tclass,
String fieldName)
需要注意的是,对象属性必须是volatile类型的,只有这样才能保证可见性。如果对象属性不是 volatile 类型的,newUpdater() 方法会抛出 IllegalArgumentException 这个运行时异常。
2.5.原子化的累加器
DoubleAccumulator、DoubleAdder、LongAccumulator 和 LongAdder,这四个类仅仅用来执行累加操作,相比原子化的基本数据类型,速度更快,但是不支持 compareAndSet() 方法。如果你仅仅需要累加操作,使用原子化的累加器性能会更好。