Bootstrap

AtomicReference源码解析

一、前言

     AtomicReference和AtomicInteger非常类似,不同之处就在于AtomicInteger是对整数的封装,而AtomicReference则对应普通的对象引用。也就是它可以保证你在修改对象引用时的线程安全性。AtomicReference是作用是对”对象”进行原子操作。 提供了一种读和写都是原子性的对象引用变量。原子意味着多个线程试图改变同一个AtomicReference(例如比较和交换操作)将不会使得AtomicReference处于不一致的状态。

二、AtomicReference的用法

① 由于AtomicReference是对一个对象进行操作,所以先创建一个对象类(JavaBean):SimpleObject类,如下所示:

package atomicreference;
/**
 * @author czd
 */
public class SimpleObject {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "SimpleObject{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public SimpleObject(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

② 创建测试类AtomicReferenceTest ,如下所示:

package atomicreference;
import java.util.concurrent.atomic.AtomicReference;
/**
 * @author czd
 */
public class AtomicReferenceTest {
    public static void main(String[] args) {
        //1、使用 null 初始值创建新的 AtomicReference。
        AtomicReference<SimpleObject> atomicReference = new AtomicReference<>();
        atomicReference.set(new SimpleObject("test1" , 10));
        SimpleObject simpleObject = atomicReference.get();
        System.out.println("simpleObject  Value: " + simpleObject.toString());
    }
}

三、源码解析

继承了哪些类

在这里插入图片描述
      由上图可知AtomicReference只继承了一个Serializable接口,其他什么也没有继承。

变量说明

//序列化序号,用来对对象进行反序列化时的判断
private static final long serialVersionUID = -1848883965231344442L;
//unsafe常量,设置为使用Unsafe.compareAndSwapInt进行更新
private static final Unsafe unsafe = Unsafe.getUnsafe();
//AtomicReference的值在内存地址的偏移量
private static final long valueOffset;
//AtomicReference当前值,泛型
private volatile V value;

valueOffset是如何获取的?

static {
    try {
        //通过unsafe变量获取valueOffset的偏移量
        valueOffset = unsafe.objectFieldOffset
            (AtomicReference.class.getDeclaredField("value"));
    } catch (Exception ex) { throw new Error(ex); }
}

    由源码得知是利用Unsafe类的内部方法进行对“value”获取其内存的偏移地址的,利用static的特性在类加载到内存中就获取到valueOffset的值。

构造方法

AtomicReference类的构造方法只有两个,如下所示:

//使用给定的初始值创建一个新的AtomicReference,即设置当前AtomicReference的值
public AtomicReference(V initialValue) {
    value = initialValue;
}
//第二个构造方法是默认的构造方法
public AtomicReference() {
}

其他方法

① get()方法。

//直接返回变量value
public final V get() {
    return value;
}

② set(V newValue)方法。

//通过参数newValue将变量value进行值的更新
public final void set(V newValue) {
    value = newValue;
}

③ lazySet(V newValue) 方法。

//通过unsafe变量最终设置为给定的值。
public final void lazySet(V newValue) {
    unsafe.putOrderedObject(this, valueOffset, newValue);
}

④ compareAndSet(V expect, V update)方法。

//CAS方法,利用判断旧值符合预期值并且更新新的值
public final boolean compareAndSet(V expect, V update) {
    return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}

⑤ getAndSet(V newValue)方法。

//先获取旧值再更新新值,还是利用unsafe的内部方法来进行操作
public final V getAndSet(V newValue) {
    return (V)unsafe.getAndSetObject(this, valueOffset, newValue);
}

    当然还有一些其他方法没有写出来,不过其内容都是利用unsafe变量的内部的本地方法进行操作,大家可以自己去了解。

四、总结

  1. 大部分的方法都是final的。
  2. AtomicReference与AtomicInteger等不一样的是其是利用泛型来对数据进行操作而不是确定的数据类型。
  3. AtomicReference中的内部方法的实现都是利用他的Unsafe变量来进行操作的。
;