CAS 相關理解與學習

在對juc包不斷升入的瞭解中,覺得有些基礎知識不得不提,一個是CAS,還有一個在文檔中常常數顯的詞語happen-before

CAS

CAS也就是campare and swap 的中文縮寫,先比較再交換,她是一種樂觀鎖的實現方式,和synchronized 這種悲觀鎖的實現方式不一樣,悲觀鎖一上來二話不說就先鎖住,但是CAS覺得一般線程
是安全的,不上鎖,但是會將當前線程獲取的值和當前的值做一個比較,如果一樣那麼就更新,如果不一樣,說明其它線程已經將值修改了,那麼當前線程就更新值,因爲更新也是需要時間的嘛,所以完之後
再和當前的值做比較,如此往復,那麼這樣的一個操作時通過自旋 volatile值實現的,CAS的基本操作在juc中體現在atomic包中,其中有針對integerbooleanlongreference的屬性,數組等的操作,
基本滿足項目中的需要,
剛纔說的CAS基本實現就是通過自旋volatile值來實現的,具體又是如何實現的呢??

//AtomicInteger

private volatile int value;
public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
}

//unsafe
/**
*中間的var2是個固定的值,
* var1 是當前線程傳進來的值,
* var5 是獲取的 value在線程執行到這個地方來的時候的值,
* 會將var1 和var5 做比較,如果相同,那麼就將 value值跟新到var4,
* 至於這一系列的操作都是在native方法中執行的
*/
public final int getAndSetInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var4));

        return var5;
}

中間的var2是個固定的值,
var1 是當前線程傳進來的值,
var5 是獲取的 value在線程執行到這個地方來的時候的值,
會將var1 和var5 做比較,如果相同,那麼就將 value值跟新到var4,
至於這一系列的操作都是在native方法中執行的

理解說明
通過volatile和Unsafe提供的CAS函數實現原子操作。 自旋+CAS的無鎖操作保證共享變量的線程安全
value是volatile類型,這保證了:當某線程修改value的值時,其他線程看到的value的值都是最新的值,即修改之後的volatile的值
通過CAS設置value。這保證了:某線程池通過CAS函數(如compareAndSet函數)設置value時,它的操作時原子性的,即線程在操作vu略時不會被中斷。

但是這可能會出現另一個問題就是就是著名的ABA問題,那麼Atomic包中是如何避免ABA問題的呢?或者說我們在想到ABA問題的時候,會想到什麼方式來避免呢??

是的沒錯,就是用一個偏移量,每次對當前值修改的時候那麼就+1操作,那麼就能夠很好的避免ABA問題!
在Atomic包中有這麼兩個類AtomicStampedReferenceAtomicMarkableReference 這兩個類都是爲了解決 ABA問題的,但是AtomicStampedReference是通過一個int類型在做偏移量,而AtomicMarkableReference
是通過一個boolean來做偏移量的

happen before

happen before 主要是針對於當前的JVM內存模型,爲了提高執行效率,可能會對我們書寫的代碼進行重排序,但是某些情況下是不會衝排序的,也就是滿足happen-before原則的代碼
happen before 8原則

  1. 程序次序規則:一個線程內,按照代碼順序,書寫在前面的操作先行發生於書寫在後面的操作;
  2. 鎖定規則:在監視器鎖上的解鎖操作必須在同一個監視器上的加鎖操作之前執行。
  3. volatile變量規則:對一個變量的寫操作先行發生於後面對這個變量的讀操作;
  4. 傳遞規則:如果操作A先行發生於操作B,而操作B又先行發生於操作C,則可以得出操作A先行發生於操作C;
  5. 線程啓動規則:Thread對象的start()方法先行發生於此線程的每一個動作;
  6. 線程中斷規則:對線程interrupt()方法的調用先行發生於被中斷線程的代碼檢測到中斷事件的發生;
  7. 線程終結規則:線程中所有的操作都先行發生於線程的終止檢測,我們可以通過Thread.join()方法結束、Thread.isAlive()的返回值手段檢測到線程已經終止執行;
  8. 對象終結規則:一個對象的初始化完成先行發生於他的finalize()方法的開始;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章