AtomicReference 源碼學(xué)習(xí)
前面寫了原子類的使用(傳送門),現(xiàn)在直接擼一下源碼吧
先看一下如何使用AR
AtomicReference<String> ar = new AtomicReference<String>();
ar.set("senninha");
//CAS操作更新
ar.compareAndSet("senninha", "senninha1");
AR類只有200多行源代碼,一下子就能擼完,先看一下成員變量吧:
private static final long serialVersionUID = -1848883965231344442L;
//unsafe類,提供cas操作的功能
private static final Unsafe unsafe = Unsafe.getUnsafe();
//value變量的偏移地址,說(shuō)的就是下面那個(gè)value,這個(gè)偏移地址在static塊里初始化,見(jiàn)下面
private static final long valueOffset;
//實(shí)際傳入需要原子操作的那個(gè)類實(shí)例
private volatile V value;
類裝載的時(shí)候初始化偏移地址:
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicReference.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
compareAndSet方法
/**
*也沒(méi)什么好說(shuō)的,就是調(diào)用Unsafe的cas操作,傳入對(duì)象,expect值,偏移地址,需要更新的值,即可,如果更新成功,返回true,如果失敗,返回false
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
這里有個(gè)坑就是,對(duì)于String變量來(lái)說(shuō),必須是對(duì)象相同才視為相同,而不是字符串的內(nèi)容相同就可以相同,如下:
AtomicReference<String> ar = new AtomicReference<String>();
ar.set("senninha");
System.out.println(ar.compareAndSet(new String("senninha"), "senninha1"));//false
weakCompareAndSet方法
//沒(méi)看出和上面那個(gè)有啥區(qū)別
public final boolean weakCompareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
還有寫奇怪的自旋set的方法,沒(méi)找到UnaryOperator的實(shí)現(xiàn)類...反正就是自旋操作
public final V getAndUpdate(UnaryOperator<V> updateFunction) {
V prev, next;
do {
prev = get();
next = updateFunction.apply(prev);
} while (!compareAndSet(prev, next));
return prev;
}