CAS樂觀鎖的ABA問題

CAS

1.CAS 原理

CAS 機制當中使用了 3 個基本操作數:內存地址 V,舊的預期值 A,要修改的新值 B。
更新一個變量的時候,只有當變量的預期值 A 和內存地址 V 當中的實際值相同時,纔會將內存地址 V 對應的值修改爲 B。

CAS 的原理就是預期值 A 與內存中的值相比較,如果相同則將內存中的值改變成新值 B。這樣比較有兩類:

  • 第一類:如果操作的是基本變量,則比較的是 值 是否相等。

  • 第二類:如果操作的是對象的引用,則比較的是對象在 內存的地址 是否相等。

2.CAS 缺點

  • CPU 開銷較大,多線程反覆嘗試更新某一個變量的時候容易出現;
  • 不能保證代碼塊的原子性,只能保證變量的原子性操作;
  • ABA 問題。

ABA 問題

1.ABA問題

線程 1 準備利用 CAS 修改變量值 A,但是在修改之前,其他線程已經將 A 變成了 B,然後又變成 A,即 A->B->A, 線程 1 執行 CAS 的時候發現仍然爲 A,所以 CAS 會操作成功,但是其實目前這個 A 已經是其他線程修改的了,但是線程 1 並不知道,最終內存值變成了 B,這就導致了 ABA 問題。

2.解決

JDK 中解決 CAS 中 ABA 問題有兩種解決方案

(一) boolean 標記:只能記錄它改變過,不能記錄改變的次數

通過添加一個 boolean 類型標記和操作的對象封裝成 Pair ,這個boolean類型標記是volatile類型的,保證所有線程的內存可見性,當有線程修改變量的時候,boolean標記就會記錄,當CAS來比較的時候會同時比較這個標記,就會知道是否被更改了,從而判斷是否執行CAS。

(二)int標記:記錄改變的次數

僅僅用一個 boolean 去標記,如果想知道被操作對象更改了幾次,就無法處理了,因爲它僅僅用一個 boolean 去標記只能判斷是否被更改過,但是如果是int類型,不僅僅可以判斷是否更改,也可以判斷更改過幾次。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章