引言

AtomicReference类表示一个可以被原子更新的对象引用。它的实现我们可以对比AtomicInteger来学习。

AtomicReference类的声明

AtomicReference的声明如下:

  1. public class AtomicReference<V> implements java.io.Serializable {}

类型变量V表示的就是对象的引用。

value和valueOffset字段

与AtomicInteger类似,AtomicReference也有value和valueOffset这两个字段,并且这两个字段的含义与它们在AtomicInteger中是一样的。

  1. private static final long valueOffset;
  2. private volatile V value;

不同的是AtomicReference中的value的类型是泛型类型V而不是简单类型。valueOffset的含义我们在AtomicInteger中已经分析过,它表示的是value字段在AtomicReference对象中的内存偏移量,它与当前AtomicReference对象一起,为CMPXCHG指令提供内存位置这个操作数。
AtomicReference的方法相比AtomicInteger也比较少,我们来简单看一下。

compareAndSet()方法

  1. public final boolean compareAndSet(V expect, V update) {
  2. return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
  3. }

这个方法在value的当前值等于参数expect值的时候,原子性的将value的值设置为update参数的值。它是通过调用Unsafe类的compareAndSwapObject()方法来实现的,该方法是一个native方法:

  1. public final native boolean compareAndSwapObject(Object var1, long var2, Object var4,
  2. Object var5);

与unsafe的compareAndSwapObject()方法一样,compareAndSwapObject实际上也就是LOCK CMPXCHG命令,前两个参数是AtomicReference对象和valueOffset,用来给定CMPXCHG命令的内存位置参数,后两个就分别对应预期值和更新值这两个参数。
compareAndSet()方法只会执行一次CMPXCHG命令,不管是否更新成功,都会返回,返回值会告诉调用者更新是否成功。

getAndSet()方法

  1. public final V getAndSet(V newValue) {
  2. return (V)unsafe.getAndSetObject(this, valueOffset, newValue);
  3. }

这个方法原子性地更新value的值为newValue指定的新值。它调用的是Unsafe类的getAndSetObject()方法:

  1. public final Object getAndSetObject(Object var1, long var2, Object var4) {
  2. Object var5;
  3. do {
  4. var5 = this.getObjectVolatile(var1, var2);
  5. } while(!this.compareAndSwapObject(var1, var2, var5, var4));
  6. return var5;
  7. }

这个方法就会循环去执行测试和替换操作了(忙循环),直到替换成功为止。与我们在AtomicInteger中调用的getAndSetInt()方法的思想是一样的,这里不再赘述。

小结

AtomicReference相比AtomicInteger,没有了自增1和自增n的操作,其他的方法思想也和AtomicInteger中的对应方法是一致的,我们这里没有很详细地介绍这些方法的实现,如果有问题,你可以参考AtomicInteger中的讲解。