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();
}
}