如果你了解了AtomicInteger的工作原理,或者看了如下文章,知道了AtomicInteger只能对当个int类型共享变量做cas的缺点。
CAS之AtomicInteger原理解析_z275598733的博客-CSDN博客
那么AtomicReference就是来解决这个问题的。原理很类似,只是AtomicReference是对对象做cas操作。从一段AtomicReference类的方法调用代码开始来对源码做分析
public class Test {
public static void main(String[] args) {
A a1 = new A(0, 0l);
A a2 = new A(1, 1l);
AtomicReference<A> ar = new AtomicReference<>(a1);
ar.getAndSet(a2);
System.out.println(ar.get().toString());
//打印对象ai的内存结构,需要引入jol-core工具包
ClassLayout classLayout = ClassLayout.parseInstance(ar);
System.out.println(classLayout.toPrintable());
}
}
@Getter
@Setter
@AllArgsConstructor
@ToString
class A{
private int v1;
private double v2;
}
从 new AtomicReference<>(a1)进入先看静态代码块和构造方法,再看 ar.getAndSet(a2) 做了什么。
public class AtomicReference<V> implements java.io.Serializable {
...
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicReference.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
//与AtomicInterger类基本一致,只不过类型由int变成了泛型V
private volatile V value;
public AtomicReference(V initialValue) {
value = initialValue;
}
//与对象
public final boolean compareAndSet(V expect, V update) {
//this-当前AtomicReference对象;valueoffest-相对AtomicReference的内存偏移量;
expect
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
//具体实现,需要进入到Unsafe类中
public final V getAndSet(V newValue) {
this-当前AtomicReference对象;valueoffest-相对this对象的内存偏移量;newValue-新对象
return (V)unsafe.getAndSetObject(this, valueOffset, newValue);
}
...
}
进入到Unsafe.getAndSetObject方法中
public final class Unsafe {
...
public final Object getAndSetObject(Object var1, long var2, Object var4) {
Object var5;
do {
//通过对象中value相对偏移量获取内存中的value对象,这里var5对其他线程是可见的, 如果不可见,那么这个值的获取就可能非内存真实值。与Unsafe.getAndAddInt异曲同工
var5 = this.getObjectVolatile(var1, var2);
//compareAndSwapObject的过程是原子性的,将重新获取到的内存对象value与var5比较,true则说明对象value并未被修改,可以将原对象改成var4。区别于Unsafe.compareAndSwapInt, 这里比较对象
} while(!this.compareAndSwapObject(var1, var2, var5, var4));
return var5;
}
//native方法,暂不深究
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
...
}
以下是debug的信息
AtomicReference类对象ar的内存结构
总而言之,AtomicReference可以保证对象的修改是线程安全的,AtomicReference对比AtomicInteger 可以在共享对象内部维护多个共享变量,但是ABA问题依然没有解决。