Java多線程系列——原子類的實現(CAS算法)


  Java提供的原子類是靠 sun 基於 CAS 實現的,CAS 是一種樂觀鎖。關於樂觀鎖與悲觀鎖

  原子變量類相當於一種泛化的 volatile 變量,能夠支持原子的和有條件的讀-改-寫操作。AtomicInteger 表示一個int類型的值,並提供了 get 和 set 方法,這些 Volatile 類型的int變量在讀取和寫入上有着相同的內存語義。它還提供了一個原子的 compareAndSet 方法(如果該方法成功執行,那么將實現與讀取/寫入一個 volatile 變量相同的內存效果),以及原子的添加、遞增和遞減等方法。AtomicInteger 表面上非常像一個擴展的 Counter 類,但在發生競爭的情況下能提供更高的可伸縮性,因為它直接利用了硬件對並發的支持。

AtomicInteger的實現


  AtomicInteger 是一個支持原子操作的 Integer 類,就是保證對 AtomicInteger 類型變量的增加和減少操作是原子性的,不會出現多個線程下的數據不一致問題。如果不使用 AtomicInteger,要實現一個按順序獲取的 ID,就必須在每次獲取時進行加鎖操作,以避免出現並發時獲取到同樣的 ID 的現象。

  接下來通過源代碼來看 AtomicInteger 具體是如何實現的原子操作。

  首先看 value 的聲明:

private volatile int value;

  volatile 修飾的 value 變量,保證了變量的可見性。

  incrementAndGet() 方法,下面是具體的代碼:

public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
 }

  通過源碼,可以知道,這個方法的做法為先獲取到當前的 value 屬性值,然后將 value 加 1,賦值給一個局部的 next 變量,然而,這兩步都是非線程安全的,但是內部有一個死循環,不斷去做 compareAndSet 操作,直到成功為止,也就是修改的根本在 compareAndSet 方法里面,compareAndSet()方法的代碼如下:

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

  compareAndSet()方法調用的compareAndSwapInt()方法的聲明如下,是一個native方法。 

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

  compareAndSet 傳入的為執行方法時獲取到的 value 屬性值,next 為加 1 后的值, compareAndSet 所做的為調用 Sun 的 UnSafe 的 compareAndSwapInt 方法來完成,此方法為 native 方法,compareAndSwapInt 基於的是 CPU 的 CAS 指令來實現的。所以基於 CAS 的操作可認為是無阻塞的,一個線程的失敗或掛起不會引起其它線程也失敗或掛起。並且由於 CAS 操作是 CPU 原語,所以性能比較好

  類似的,還有 decrementAndGet() 方法。它和 incrementAndGet() 的區別是將 value 減 1,賦值給next 變量。

      AtomicInteger 中還有 getAndIncrement() 和 getAndDecrement() 方法,他們的實現原理和上面的兩個方法完全相同,區別是返回值不同,前兩個方法返回的是改變之后的值,即 next。而這兩個方法返回的是改變之前的值,即 current。還有很多的其他方法,就不列舉了。

CAS算法

CAS(Compare-And-Swap)算法保證數據操作的原子性。

CAS 算法是硬件對於並發操作共享數據的支持。

CAS 包含了三個操作數:
  內存值 V
  預估值 A
  更新值 B

當且僅當 V == A 時,V 將被賦值為 B,否則循環着不斷進行判斷 V 與 A 是否相等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM