Android開發——CAS基本原理


CAS(比較並且交換)

什么是原子操作?如何實現原子操作?

假定有兩個操作A和B(A和B可能都很復雜),如果從執行A的線程來看,當另一個線程執行B時,要么將B全部執行完,要么完全不執行B,那么A和B對彼此來說是原子的。

實現原子操作可以使用鎖,鎖機制,滿足基本的需求是沒有問題的了,但是有的時候我們的需求並非這么簡單,我們需要更有效,更加靈活的機制,synchronized關鍵字是基於阻塞的鎖機制,也就是說當一個線程擁有鎖的時候,訪問同一資源的其它線程需要等待,直到該線程釋放鎖,

這里會有些問題:首先,如果被阻塞的線程優先級很高很重要怎么辦?其次,如果獲得鎖的線程一直不釋放鎖怎么辦?(這種情況是非常糟糕的)。還有一種情況,如果有大量的線程來競爭資源,那CPU將會花費大量的時間和資源來處理這些競爭,同時,還有可能出現一些例如死鎖之類的情況,最后,其實鎖機制是一種比較粗糙,粒度比較大的機制,相對於像計數器這樣的需求有點兒過於笨重。

實現原子操作還可以使用當前的處理器基本都支持CAS()的指令,只不過每個廠家所實現的算法並不一樣,每一個CAS操作過程都包含三個運算符:一個內存地址V,一個期望的值A和一個新值B,操作的時候如果這個地址上存放的值等於這個期望的值A,則將地址上的值賦為新值B,否則不做任何操作。

CAS的基本思路就是,如果這個地址上的值和期望的值相等,則給其賦予新值,否則不做任何事兒,但是要返回原值是多少。循環CAS就是在一個循環里不斷的做cas操作,直到成功為止。

 

 

CAS實現原子操作的三大問題及解決方式

 

ABA問題。

 

因為CAS需要在操作值的時候,檢查值有沒有發生變化,如果沒有發生變化則更新,但是如果一個值原來是A,變成了B,又變成了A,那么使用CAS進行檢查時會發現它的值沒有發生變化,但是實際上卻變化了。

利於版本戳來解決,沒修改一次,則版本號+1

循環時間長開銷大。

自旋CAS如果長時間不成功,會給CPU帶來非常大的執行開銷。

只能保證一個共享變量的原子操作。

當對一個共享變量執行操作時,我們可以使用循環CAS的方式來保證原子操作,但是對多個共享變量操作時,循環CAS就無法保證操作的原子性。

1、可以用鎖。 

2、把多個共享變量合並成一個共享變量來操作。比如,有兩個共享變量i2j=a,合並一下ij=2a,然后用CAS來操作ij。從Java 1.5開始,JDK提供了AtomicReference類來保證引用對象之間的原子性,就可以把多個變量放在一個對象里來進行CAS操作。

 


免責聲明!

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



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