深入瞭解java之CAS詳解

2022-03-14 19:00:30
本篇文章給大家帶來了關於的相關問題,其中主要介紹了關於CAS的相關問題,CAS(compare and swap),比較並交換,可以解決多執行緒並行情況下使用鎖造成效能損耗的一種機制,希望對大家有幫助。

推薦學習:《》

CAS解釋:

CAS(compare and swap),比較並交換。可以解決多執行緒並行情況下使用鎖造成效能損耗的一種機制.CAS 操作包含三個運算元—記憶體位置(V)、預期原值(A)和新值(B)。如果記憶體位置的值與預期原值相匹配,那麼處理器會自動將該位置值更新為新值。否則,處理器不做任何操作。一個執行緒從主記憶體中得到num值,並對num進行操作,寫入值的時候,執行緒會把第一次取到的num值和主記憶體中num值進行比較,如果相等,就會將改變後的num寫入主記憶體,如果不相等,則一直迴圈對比,知道成功為止。

CAS產生:

在修飾共用變數的時候經常使用volatile關鍵字,但是volatile值有可見性和禁止指令重拍(有序性),無法保證原子性。雖然在單執行緒中沒有問題,但是多執行緒就會出現各種問題,造成現場不安全的現象。所以jdk1.5後產生了CAS利用CPU原語(不可分割,連續不中斷)保證現場操作原子性。

CAS應用:

在JDK1.5 中新增java.util.concurrent(JUC)就是建立在CAS之上的。相對於對於synchronized這種鎖機制,CAS是非阻塞演演算法的一種常見實現。所以JUC在效能上有了很大的提升。

比如AtomicInteger類,AtomicInteger是執行緒安全的的,下面是原始碼

進入unsafe看到do while自迴圈,這裡的自迴圈,就是在 判斷預期原值 如果與原來的值不符合,會再回圈取原值,再走CAS流程,直到能夠把新值賦值成功。

CAS優點

cas是一種樂觀鎖的思想,而且是一種非阻塞的輕量級的樂觀鎖,非阻塞式是指一個執行緒的失敗或者掛起不應該影響其他執行緒的失敗或掛起的演演算法。

CAS 缺點

  1. 迴圈時間長開銷大,佔用CPU資源。如果自旋鎖長時間不成功,會給CPU帶來很大的開銷。如果JVM能支援處理器提供的pause指令那麼效率會有一定的提升,pause指令有兩個作用,第一它可以延遲流水線執行指令(de-pipeline),使CPU不會消耗過多的執行資源,延遲的時間取決於具體實現的版本,在一些處理器上延遲時間是零。第二它可以避免在退出迴圈的時候因記憶體順序衝突(memory order violation)而引起CPU流水線被清空(CPU pipeline flush),從而提高CPU的執行效率。
  2. 只能保證一個共用變數的原子操作。當對一個共用變數執行操作時,我們可以使用迴圈CAS的方式來保證原子操作,但是對多個共用變數操作時,迴圈CAS就無法保證操作的原子性,這個時候就可以用鎖,或者有一個取巧的辦法,就是把多個共用變數合併成一個共用變數來操作。比如有兩個共用變數i=2,j=a,合併一下ij=2a,然後用CAS來操作ij。從Java1.5開始JDK提供了AtomicReference類來保證參照物件之間的原子性,你可以把多個變數放在一個物件裡來進行CAS操作。
  3. ABA問題

解決ABA問題(如果值考慮收尾,不考慮過程可以忽略改問題)

  1. 新增版本號
  2. AtomicStampedReference

從Java1.5開始JDK的atomic包裡提供了一個類AtomicStampedReference來解決ABA問題。這個類的compareAndSet方法作用是首先檢查當前參照是否等於預期參照,並且當前標誌是否等於預期標誌,如 全部相等,則以原子方式將該參照和該標誌的值設定為給定的更新值。

CAS使用的時機

  1. 執行緒數較少、等待時間短可以採用自旋鎖進行CAS嘗試拿鎖,較於synchronized高效。
  2. 執行緒數較大、等待時間長,不建議使用自旋鎖,佔用CPU較高

推薦學習:《》

以上就是深入瞭解java之CAS詳解的詳細內容,更多請關注TW511.COM其它相關文章!