Java CAS樂觀鎖

Java 的 concurrent 包中藉助 CAS 實現了區別於 synchronized 同步鎖的一種樂觀鎖,以及一系列的原子數據。
CAS 有3個操做數,內存值V,舊的預期值A,要修改的新值B。當且僅當預期值A和內存值V相同時,將內存值V修改成B,不然什麼都不作。
CAS 經過調用 JNI 的代碼實現的,容許 java 調用其餘語言,而 compareAndSwap 就是藉助 C 來調用 CPU 底層指令實現的,底層實現的方式仍然是排它鎖,不過是由 CPU 來觸發,比起 Synchronized 性能好不少。
Unsafe 類是 java 中很是特別的一個類,提供的操做能夠直接讀寫內存、得到地址偏移值、鎖定或釋放線程。

AtomicInteger類:java

public class AtomicInteger extends Number implements Serializable {
    private static final long serialVersionUID = 6214790243416807050L;
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;
    private volatile int value;



    public AtomicInteger(int var1) {
        this.value = var1;
    }
    …..
    …..
    public final boolean compareAndSet(int var1, int var2) {
        return unsafe.compareAndSwapInt(this, valueOffset, var1, var2);
    }

    public final boolean weakCompareAndSet(int var1, int var2) {
        return unsafe.compareAndSwapInt(this, valueOffset, var1, var2);
    }



    public final int getAndUpdate(IntUnaryOperator var1) {

        int var2;

        int var3;

        do {

            var2 = this.get();

            var3 = var1.applyAsInt(var2);

       } while(!this.compareAndSet(var2, var3));


       return var2;

   }



   public final int updateAndGet(IntUnaryOperator var1) {

        int var2;

        int var3;

        do {

           var2 = this.get();

           var3 = var1.applyAsInt(var2);

       } while(!this.compareAndSet(var2, var3));


       return var3;

   }
    ….
    ….
}


AtomicInteger 中咱們能夠看到:app

  1. value 被申明爲 volatile,保證順序和可見性;
  2. valueOffset 記錄了 value 在內存中的偏移;
  3. compareAndSwapInt 對內存中的 value 進行 CAS 操做。


unsafe.cpp 中 compareAndSwapInt 實現代碼: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


Atomic: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  
  }  
}

從代碼中咱們能夠看出,compareAndSwapInt 底層仍是用的是排他鎖,只不過是 CPU 觸發的。
 this

相關文章
相關標籤/搜索