AtomicReference作用
AtomicReference是作用是对”对象”进行原子操作。
提供了一种读和写都是原子性的对象引用变量。原子意味着多个线程试图改变同一个AtomicReference(例如比较和交换操作)将不会使得AtomicReference处于不一致的状态。
AtomicReference源码
public class AtomicReference<V> 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);
}
//.....省略.....
}
volatile:多线程读写过程中能够保持它们的可见性。即要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
value是volatile类型,保证value值永远是最新的value值,线程在操作value时不会被中断。
通过Unsafe.compareAndSwapObject设置的value,保证操作是原子性的,线程在操作value时不会被中断。
AtomicReference示例
先定义一个People类
People类
public 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 +
'}';
}
}
入口函数
public class MainDemo {
public static void main(String[] args) {
People people1 =new People("Bom", 0);
People people2 =new People("Tom",10);
//先初始化一个值,如果不初始化则默认值为null
AtomicReference<People> reference = new AtomicReference<>(people1);
People people3 = reference.get();
if (people3.equals(people1)) {
System.out.println("people3:" + people3);
} else {
System.out.println("else:" + people3);
}
/**
* 当前值:拿当前值和reference.get()获取到的值去比较,如果相等则true并更新值为期望值
* 期望值:如果返回true则更新为期望值,如果返回false则不更新值
*/
boolean b = reference.compareAndSet(null, people2);
System.out.println("myClass.main-"+b+"--"+reference.get());
boolean b1 = reference.compareAndSet(people1, people2);
System.out.println("myClass.main-"+b1+"--"+reference.get());
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Thread1-----------");
People people = reference.get();
people.setName("Tom1");
people.setAge(people.getAge()+1);
reference.getAndSet(people);
System.out.println("Thread1:"+reference.get().toString());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Thread2-----------");
People people = reference.get();
people.setName("Tom2");
people.setAge(people.getAge()+1);
reference.getAndSet(people);
System.out.println("Thread2:"+reference.get().toString());
}
}).start();
}
}
打印结果
people3:People{name='Bom', age=0}
myClass.main-false--People{name='Bom', age=0}
myClass.main-true--People{name='Tom', age=10}
Thread2-----------
Thread2:People{name='Tom2', age=11}
Thread1-----------
Thread1:People{name='Tom1', age=12}