用CAS實現volatile原子性方式簡介


當線程用synchronize鎖的時候,可以保證線程是具有原子性 可見性 有序性的。

 

原子性,

表現為每個可以單獨操作,不互相依賴,在線程中表現為每個線程都有所以它自己的一份copy值,不定期的刷新到主內存。(如果有鎖,ulock時刷新到主內存)

而volatile變量不具有原子性,每次讀寫都是自己去主內存讀主內存的值,也真是由於此種原因不能進行計數器操作,例如:

volatile i =1;

線程A,線程B 同時 i++;

i++ 即

i=i; //從主內存中讀   1

i+1; //通過獲取的值。計算 2

i=i+1; //把計算的值寫入主內存中 3

 

當線程執行順序如下時 A1 – >B1—>A2—>A3—>A1—>B2—>B3, 最后結果導致運行了兩次結果還是2

 

對此,

1, 可以用CAS算法進行改進

CAS也可成為樂觀鎖,實現原理,通過保存原有值進行比較結果,直到更改成功

實現原理,CAS保存了3個值 H當前值(作為預期值),V內存值,S計算值

代碼實現如下

public final int casTest() {
        for (;;) {
            int h=i;                  //A線程叫AH,B線程描述為BH        1
            int s = i + 1;         // A線程叫AS,B線程描述為BS         2

             if(h==i){           // 比較內存值和預期值                           3

               i=s;                  // 如果相同,賦值,成功CAS              4

              break;

            }
            }

 

A1 (A開始時用AH保存內存中此時的i值)->

B1(B開始時也用BH保存當前i值)->

A2  (把計算值2賦給AS)

A3(比較保存的AH和讀取內存值AV,都是等於1,未改變)

A4(所以CAS成功,把AS即2放入內存中)

B2(把計算值2賦給BS)

B3(比較BH和讀取當前內存值BV,BH是1,BV是2,所以不相等,返回到B1)

B1   (故重新取出內存值i,重復計算,此時BH=BV=2,BS=3賦給主內存,完成計數)

 

 

其實在並發包中的實現原理我也差不多(待考證……),只是用的是native方法,看代碼

/**
* Atomically sets to the given value and returns the old value.
*
* @param newValue the new value
* @return the previous value
*/
public final int getAndSet(int newValue) {
    for (;;) {
        int current = get();   // step 1
        if (compareAndSet(current, newValue)) //step 2
            return current;
    }
}

step1 相當於獲取當前值h,並保存

step2  newValue相當於比較s,計算值

 

 

2, 當然可以用synchronize鎖進行同步(略)


免責聲明!

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



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