引用原子类
包含三种:
AtomicReference
: 引用类型原子类。实现原理:CAS。
compareAndSet()
:无法通过匿名对象进行比较,因为比较的内容是地址而不是Obejct.equals()
。
AtomicStampedReference
: 带有引用版本号的原子类。实现原理:CAS同时C版本号。
compareAndSet()
:比较内容地址的同时对版本号做出比较。
AtomicMarkableReference
: 带有标记的引用原子类。实现原理:CAS同时C标记。
compareAndSet()
:比较内容地址的同时对标记做出比较。
public class Main {
public static void main(String[] args) throws Exception {
Person birdy = new Person("birdy");
AtomicReference<Person> atomicRef = new AtomicReference<>(birdy);
atomicRef.compareAndSet(birdy, new Person("alexander")); // success
atomicRef.compareAndSet(new Person("birdy"), new Person("alexander")); // false
AtomicStampedReference<Person> stampedRef = new AtomicStampedReference<>(birdy, 1);
stampedRef.compareAndSet(birdy, new Person("alexander"), 1, 2);
AtomicMarkableReference<Person> markRef = new AtomicMarkableReference<>(birdy, true);
markRef.compareAndSet(birdy, new Person("alexander"), true, false);
}
}
解决的问题
AtomicStampedReference
和AtomicMarkableReference
共同解决多线程下访问数据操作ABA不同步的问题(即:两个线程并发操作,由于更新不同步导致更新错误。对应应用:Github代码提交)
属性修改器
在类中需要原子地get/set
某个属性,可以使用属性修改器。包含三种:
AtomicIntegerFiledUpdater
: 原子整型成员修改器AtomicLongFieldUpdater
: 原子长整型成员修改器AtomicReferenceFieldUpdater
: 原子引用成员修改器
针对AtomicLongFieldUpdater
分析,它的构造是protected
的,它有一个入口静态方法:newUpdater()
newUpdater()
@CallerSensitive
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,String fieldName) {
Class<?> caller = Reflection.getCallerClass();
if (AtomicLong.VM_SUPPORTS_LONG_CAS)
return new CASUpdater<U>(tclass, fieldName, caller);
else
return new LockedUpdater<U>(tclass, fieldName, caller);
}
发现有两种更新器:
CASUpdater
: 通过CAS机制实现更新。LockedUpdater
: 通过锁定两块长整型地址修改属性,用于x32
环境。
使用方法
class Person {
private String name;
private volatile long balance; // 必须使用volatile定义Updater操作的成员
private static final AtomicLongFieldUpdater<Person> UPDATER =
AtomicLongFieldUpdater.newUpdater(Person.class, "balance");
public long getBalance() {
return UPDATER.get(this);
}
public void setBalance(long balance) {
UPDATER.set(this, balance);
}