CAS也是鎖

CAS(CompareAndSwap)顧名思義比較再交換。先比較,發現與預期一致,說明沒有其餘線程改動過,因而就交換;若是不一致說明改動過,就再來一次,如此往復。java

int prev, next;
do {
    prev = get();
    next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(prev, next));
return next;

這是一種自旋的方式保證線程安全,但是compareAndSet這個比較再交換是原子的嗎?先比較發現與預期一致了,準備交換的時候另外一個線程來改了怎麼辦?
點進去看源碼:安全

public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

這個unsafe的方法都是native方法,app

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

只能打開openJDK看源碼了oop

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

核心方法是cmpxchg方法性能

inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
  // alternative for InterlockedCompareExchange
  int mp = os::is_MP();
  __asm {
    mov edx, dest
    mov ecx, exchange_value
    mov eax, compare_value
    LOCK_IF_MP(mp)
    cmpxchg dword ptr [edx], ecx
  }
}

原來LOCK_IF_MP這裏加了鎖,才保證了原子性。所謂「無鎖」是在Java層面上沒有鎖,但其實在操做系統的CPU指令層面是加了鎖的。這個鎖比java上的鎖性能好不少。this

相關文章
相關標籤/搜索