什麼是CAS
compare and swap
以CAS
的方式對屬性private int value = 0;
進行遞增操作
- 讀取
value
的值 - 將其賦值給臨時變量
a
,此時a = 0;
- 從
a
中獲取值進行計算,將所得結果賦值給變量b
,此時a = 0; b =1;
- 重新讀取
value
的值,與a
進行比較 - 如果兩個值相等,則將
b
中的值寫入到value
中 - 如果不相等,則從頭開始讀取
value
的,賦值給a
,計算,再進行讀取比較,直到賦值成功爲止!
源碼
以AtomicInteger
爲例,追溯其incrementAndGet
的邏輯
AtomicInteger counter = new AtomicInteger();
counter.incrementAndGet();
在incrementAndGet
方法中
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
incrementAndGet
方法先increment
然後 get
調用了sun.misc.Unsafe
類的 getAndAddInt
方法,而裏面調用的是 getAndAddInt
,是先get
然後再add
,所以這裏需要加1
getAndAddInt
中
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
v = getIntVolatile(o, offset);
} while (!compareAndSwapInt(o, offset, v, v + delta));
return v;
}
調用 compareAndSwapInt
方法,而此方法是一個native
方法,因此我們需要從hotspot
源碼src/share/vm/prims/unsafe.cpp
中的實現
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
UnsafeWrapper("Unsafe_CompareAndSwapInt");
oop p = JNIHandles::resolve(obj);
jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END
這裏調用了Atomic
的cmpxchg
方法,在src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp
中
inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) {
int mp = os::is_MP();
__asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)"
: "=a" (exchange_value)
: "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
: "cc", "memory");
return exchange_value;
}
這裏調用了彙編中的cmpxchgl
指令