解決CAS演算法的 ABA 漏洞問題

2021-09-25 06:43:27 字數 1913 閱讀 9154

在將如何去解決去解決cas的aba問題時,我們先來說一下什麼是cas,cas全稱 compare-and-swap ,cpu併發原語。執行是連續的,不允許被中斷,不會造成資料不一致問題。

cas演算法:它包含三個引數cas(v,e,n): v表示要更新的變數,e表示預期值,n表示新值。僅當v值等於e值時,才會將v的值設為n,如果v值和e值不同,則說明已經有其他執行緒做了更新,則當前執行緒什麼都不做。最後,cas返回當前v的真實值。

cas操作是抱著樂觀的態度進行的,它總是認為自己可以成功完成操作。當多個執行緒同時使用cas操作乙個變數時,只有乙個會勝出,並成功更新,其餘均會失敗。失敗的執行緒不會被掛起,僅是被告知失敗,並且允許再次嘗試,當然也允許失敗的執行緒放棄操作。基於這樣的原理,cas操作即使沒有鎖,也可以發現其他執行緒對當前執行緒的干擾,並進行恰當的處理。

然後我們再講一講aba問題。

aba問題: 假定在某個時刻某個執行緒從記憶體中取出a,然後在下個時刻準備更新這個值;在這個時間差內資料發生了改變;比如 假設執行緒1從記憶體中取出了a,執行緒2也從記憶體中取出了a,並且將值修改為b,最後又改為a,當執行緒1去更新值得時候發現記憶體中的資料和執行緒備份資料相同,可以更新;但是此時記憶體中的值其實發生了變化的,只不過又變回去了。

又比如現有乙個用單向鍊錶實現的堆疊,棧頂為a,這時執行緒t1已經知道a.next為b,然後希望用cas將棧頂替換為b:head.compareandset(a,b);

在t1執行上面這條指令之前,執行緒t2介入,將a、b出棧,再pushd、c、a,,而物件b此時處於游離狀態:

此時輪到執行緒t1執行cas操作,檢測發現棧頂仍為a,所以cas成功,棧頂變為b,但實際上b.next為null,所以此時的情況變為:

其中棧中只有b乙個元素,c和d組成的鍊錶不再存在於堆疊中,平白無故就把c、d丟掉了。

我們用一段簡單的**來演示一下aba問題:

public class aba 

});thread t2 = new thread(new runnable() catch (interruptedexception e)

boolean c3 = atomicint.compareandset(100, 101);

system.out.println(c3);

}});

t1.start();

t2.start();

}}

public class aba  catch (interruptedexception e) 

atomicstampedref.compareandset(100, 101, atomicstampedref.getstamp(), atomicstampedref.getstamp() + 1);

atomicstampedref.compareandset(101, 100, atomicstampedref.getstamp(), atomicstampedref.getstamp() + 1);

}});

thread reft2 = new thread(new runnable() catch (interruptedexception e)

boolean c3 = atomicstampedref.compareandset(100, 101, stamp, stamp + 1);

system.out.println(c3);

}});

reft1.start();

reft2.start();

}}

由於在第乙個執行緒中修改過atomicstampedref的值,所以它的版本號也變更了,而在第二個執行緒中由於先拿到atomicstampedref的版本號,然後二線程睡眠了一段時間,這段時間裡atomicstampedref的值已經變換過了,版本號就不同了,所以執行緒二的操作就失敗了。

CAS的ABA問題詳解

aba問題 執行緒1搶先獲得cpu時間片,而執行緒2因為其他原因阻塞了,執行緒1取值與期望的a值比較,發現相等然後將值更新為b,然後這個時候出現了執行緒3,期望值為b,欲更新的值為a,執行緒3取值與期望的值b比較,發現相等則將值更新為a,此時執行緒2從阻塞中恢復,並且獲得了cpu時間片,這時候執行緒...

CAS的ABA問題詳解

在多執行緒場景下cas會出現aba問題,關於aba問題這裡簡單科普下,例如有2個執行緒同時對同乙個值 初始值為a 進行cas操作,這三個執行緒如下 1.執行緒1,期望值為a,欲更新的值為b 2.執行緒2,期望值為a,欲更新的值為b 執行緒1搶先獲得cpu時間片,而執行緒2因為其他原因阻塞了,執行緒1...

併發程式設計cas的aba問題

多執行緒環境下,兩個執行緒a,b可能會對共享資料m進行操作。為了保證乙個執行緒在讀到資料跟寫入資料之間沒有被其他執行緒修改過,使用cas解決。cas 更改之前先判斷舊值是否有變化,如果沒有變化,認為沒有執行緒對該共享值做過操作。這種認為是有一下問題的,時執行緒a 執行緒bt1 讀m值為1 t2讀m值...