CAS(樂觀鎖)與ABA問題


cas是什么

  CAS 全稱 compare and swap 或者compare and exchange  比較並且交換。用於在沒有鎖的情況下,多個線程對同一個值的更新。

 

 

cas原理

  例如,我們對一個int i進行遞增操作。原來,為了線程安全,需要在遞增代碼上加一把鎖 sync 。CAS的實現方式為:不去加鎖,讀取當前的值,將原值存入E中,然后計算,得到計算結果1,這個時候的新值存入V中。然后調用一個比較並交換的方法(底層匯編指令) 這個方法的作用是:如果E和現在的i值相等,說明沒有地方對原值進行過操作。那么就將i的值替換為V的值。
  如果有別的線程對i進行操作了(例如:i被修改為了2),那么將i的新值讀取,然后再進行一次計算操作(將i=2 作為最初值,進行計算,得到結果3 )。然后再次調用比較並交換的方法,去進行值的更新操作。一直循環,直到更新成功(有的鎖在更新到一定次數后,會進行鎖升級,但是這個跟CAS沒關系)

   CAS底層原理

  cas追代碼的時候,可以追到native部分,但是,這里面提供的都是一些接口,但是沒有具體的底層實現。具體的實現,需要看虛擬機的實現。

  jvm的底層實現分為不同的公司的不同實現:Oracle的為hotSpot實現,這個是最常見的。我們可以看到代碼的開源版本是openjdk。比如阿里的taobaoVM 。Ibm 的J9等。

  在openjdk 中,unsafe類在實現CompareAndSwapInt 方法時,是調用的Atomic類的cmpxchg方法,然后一通方法調用,最終調用到匯編語言的 lock_if_mp(lock  if multi processors 如果是多個cpu 那么會鎖定) cmpxchg 這兩個 指令 ,最終執行 lock cmpxchg 指令
這里的lock是一一個鎖定北橋芯片的鎖,用於解決當前cpu在進行比較和修改的時候的其他cpu對該值進行操作的問題。保證線程安全。

aba問題

  在線程A進來時,讀取到的值為1。在A進行計算的時候線程B取到了i的值,然后更新為了2。然后線程C又取到i=2的值,進行C的計算后,然后得到結果為1 又將i的值修改為了1 這個時候,線程A進行判斷的時候,會認為在其計算過程中沒有其他線程對i進行過操作。ABA有的會產生影響,有的不會,如果沒有影響,不需要考慮該問題。

aba問題解決

  解決方法:加上版本號,每個線程讀取完,賦值的時候,修改版本號,比較的時候,對比i值+版本號。


免責聲明!

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



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