CAS -- ABA問題的解決方案


我們現在來說什么是ABA問題。假設內存中有一個值為A的變量,存儲在地址V中。

此時有三個線程想使用CAS的方式更新這個變量的值,每個線程的執行時間有略微偏差。線程1和線程2已經獲取當前值,線程3還未獲取當前值。

接下來,線程1先一步執行成功,把當前值成功從A更新為B;同時線程2因為某種原因???被阻塞住,沒有做更新操作;線程3在線程1更新之后,獲取了當前值B。

為什么線程3又反過來操作???是自旋嗎???

在之后,線程2仍然處於阻塞狀態,線程3繼續執行,成功把當前值從B更新成了A。

最后,線程2終於恢復了運行狀態,由於阻塞之前已經獲得了“當前值A”,並且經過compare檢測,內存地址V中的實際值也是A,所以成功把變量值A更新成了B。

個人見解: 不是說一定出現ABA情況,是說有出現這種情況的可能性。也就是舉一個特例來說明問題的可能性???

看起來這個例子沒啥問題,但如果結合實際,就可以發現它的問題所在。

我們假設一個提款機的例子。假設有一個遵循CAS原理的提款機,小灰有100元存款,要用這個提款機來提款50元 。

由於提款機硬件出了點問題,小灰的提款操作被同時提交了兩次,開啟了兩個線程,兩個線程都是獲取當前值100元,要更新成50元。

理想情況下,應該一個線程更新成功,一個線程更新失敗,小灰的存款值被扣一次。

有個問題: 點兩次正常情況下不是兩次都成功嗎?為什么一次成功一次失敗???

線程1首先執行成功,把余額從100改成50.線程2因為某種原因 什么原因???阻塞。這時,小灰的媽媽剛好給小灰匯款50元。

線程2仍然是阻塞狀態,線程3執行成功,把余額從50改成了100。

線程2恢復運行,由於阻塞之前獲得了“當前值”100,並且經過compare檢測,此時存款實際值也是100,所以會成功把變量值100更新成50。

原本線程2應當提交失敗,小灰的正確余額應該保持100元,結果由於ABA問題提交成功了。

怎么解決呢?加個版本號就可以了。

真正要做到嚴謹的CAS機制,我們在compare階段不僅要比較期望值A和地址V中的實際值,還要比較變量的版本號是否一致。

我們仍然以剛才的例子來說明,假設地址V中存儲着變量值A,當前版本號是01。線程1獲取了當前值A和版本號01,想要更新為B,但是被阻塞了。

這時候,內存地址V中變量發生了多次改變,版本號提升為03,但是變量值仍然是A。

隨后線程1恢復運行,進行compare操作。經過比較,線程1所獲得的值和地址的實際值都是A,但是版本號不相等,所以這一次更新失敗。

 

在Java中,AtomicStampedReference類???就實現了用版本號作比較額CAS機制。

 

1. java語言CAS底層如何實現?

利用unsafe提供的原子性操作方法(我也不太清楚???)。

2.什么事ABA問題?怎么解決?

當一個值從A變成B,又更新回A,普通CAS機制會誤判通過檢測。

利用版本號比較可以有效解決ABA問題。

 

 

 

 

參考文檔:https://blog.csdn.net/qq_32998153/article/details/79529704 


免責聲明!

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



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