AtomicReference

AtomicReference是作用是对”对象”进行原子操作。

源码

public class AtomicReference implements Serializable {
    private static final long serialVersionUID = -1848883965231344442L;
    private static final Unsafe unsafe = Unsafe.getUnsafe();//通过 unsafe 实现原子操作
    private static final long valueOffset;
    private volatile V value;//通过 volatile 实现原子操作

    public AtomicReference(V var1) {
        this.value = var1;
    }

    public AtomicReference() {
    }

    //通过 volatile 实现原子操作
    public final V get() {
        return this.value;
    }

    //不是原子操作-慎用
    public final void set(V var1) {
        this.value = var1;
    }

    //通过 unsafe 实现原子操作
    public final void lazySet(V var1) {
        unsafe.putOrderedObject(this, valueOffset, var1);
    }

    //通过 unsafe 实现原子操作
     /**
         * var1当前值:拿当前值value和var1值去比较,如果相等返回true并更新值为var2期望值
         * var2期望值:如果返回true则更新为期望值,如果返回false则不更新值
         */
    public final boolean compareAndSet(V var1, V var2) {
        return unsafe.compareAndSwapObject(this, valueOffset, var1, var2);
    }

    //通过 unsafe 实现原子操作
    public final boolean weakCompareAndSet(V var1, V var2) {
        return unsafe.compareAndSwapObject(this, valueOffset, var1, var2);
    }

    //通过 unsafe 实现原子操作
    public final V getAndSet(V var1) {
        return unsafe.getAndSetObject(this, valueOffset, var1);
    }

    //.....省略.....
}

使用

实体类

class People {
    private String name;
    private int age;

    public People(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
    private static People p1 = new People("Tom", 12);
    private static People p2 = new People("Jack", 13);
    private static AtomicReference ar = new AtomicReference(p1);

    public static void main(String[] args) throws InterruptedException {
        People people = ar.get();
        System.out.println(people == p1);//true

        System.out.println(ar.compareAndSet(null, p2));//false
        System.out.println(ar.get());//People{name='Tom', age=12}

        System.out.println(ar.compareAndSet(p1, p2));//true
        System.out.println(ar.get());//People{name='Jack', age=13}
    }

AtomicReference和AtomicInteger一样,有ABA问题,用AtomicStampedReference解决

public class Test {
    private static People p1 = new People("Tom", 12);
    private static People p2 = new People("Jack", 13);
    private static AtomicReference at = new AtomicReference(p1);
    private static AtomicStampedReference asr = new AtomicStampedReference(p1, 0);

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
                at.compareAndSet(p1, p2);
                at.compareAndSet(p2, p1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t1.start();

        Thread t2 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
                boolean b = at.compareAndSet(p1, p2);
                System.out.println("AtomicReference " + b);//AtomicReference true
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t2.start();

        Thread t3 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
                asr.compareAndSet(p1, p2, asr.getStamp(), asr.getStamp() + 1);
                asr.compareAndSet(p2, p1, asr.getStamp(), asr.getStamp() + 1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t3.start();

        Thread t4 = new Thread(() -> {
            try {
                int stamp = asr.getStamp();
                TimeUnit.SECONDS.sleep(2);
                boolean b = asr.compareAndSet(p1, p2, stamp, stamp + 1);
                System.out.println("AtomicStampedReference " + b);//AtomicStampedReference false
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t4.start();

    }

}


你可能感兴趣的:(java)