1. 程式人生 > >淺談CAS原理

淺談CAS原理

    java併發程式設計也研究了一段時間了,對CAS的原理總是不太理解,今天再研究了一下,記錄一些自己的理解。
    說到CAS,再java中的某些情況下,甚至jdk1.5以後的大多數情況,併發程式設計都是用CAS實現的,那麼CAS到底如何能夠實現鎖的功能呢?
    拿a++操作舉例
public final int getAndIncrement() {  
    for (;;) {  
        int current = get();  
        int next = current + 1;  
        if (compareAndSet(current, next))  
            return current;  
    }  
}   

這裡面的compareAndSet的功能為,a與current比較,如果相等則把a的值變為next;這時候可以保證在int next = current + 1;與if();之間不會被其他執行緒搶佔(因為a的值在這段時間內沒有變),如果被搶佔則會做自旋操作。這就在某種程度上可以實現原子性操作。

這是一種不加鎖而實現操作原子化的一種巧妙的程式設計方式,不僅在java的jvm種,甚至在作業系統的底層併發實現機制中也有CAS的大量應用。

但是這種方式有沒有缺點呢?

當然也會有:
1、ABA問題

CAS操作容易導致ABA問題,也就是在做a++之間,a可能被多個執行緒修改過了,只不過回到了最初的值,這時CAS會認為a的值沒有變。a在外面 逛了一圈回來,你能保證它沒有做任何壞事,不能!!也許它討閒,把b的值減了一下,把c的值加了一下等等,更有甚者如果a是一個物件,這個物件有可能是新 創建出來的,a是一個引用呢情況又如何,所以這裡面還是存在著很多問題的,解決ABA問題的方法有很多,可以考慮增加一個修改計數,只有修改計數不變的且 a值不變的情況下才做a++,也可以考慮引入版本號,當版本號相同時才做a++操作等,這和事務原子性處理有點類似!


2、比較花費CPU資源,即使沒有任何爭用也會做一些無用功。

3、會增加程式測試的複雜度,稍不注意就會出現問題。

總結

可以用CAS在無鎖的情況下實現原子操作,但要明確應用場合,非常簡單的操作且又不想引入鎖可以考慮使用CAS操作,當想要非阻塞地完成某一操作也可以考慮CAS。不推薦在複雜操作中引入CAS,會使程式可讀性變差,且難以測試,同時會出現ABA問題。