JDK對CAS ABA問題解決-AtomicMarkableReference和AtomicStampedReference


我們知道AtomicInteger和AtomicLong的原子操作,但是在這兩個類在CAS操作的時候會遇到ABA問題,可能大家會疑問什么是ABA問題呢,請待我細細道來:

ABA問題:簡單講就是多線程環境,2次讀寫中一個線程修改A->B,然后又B->A,另一個線程看到的值未改變,又繼續修改成自己的期望值。當然我們如果不關心過程,只關心結果,那么這個就是無所謂的ABA問題。

  • 為了解決ABA問題,偉大的java為我們提供了AtomicMarkableReference和AtomicStampedReference類,為我們解決了問題
  • AtomicStampedReference是利用版本戳的形式記錄了每次改變以后的版本號,這樣的話就不會存在ABA問題了,在這里我借鑒一下別人舉得例子

舉個通俗點的例子,你倒了一杯水放桌子上,干了點別的事,然后同事把你水喝了又給你重新倒了一杯水,你回來看水還在,拿起來就喝,如果你不管水中間被人喝過,只關心水還在,這就是ABA問題。如果你是一個講衛生講文明的小伙子,不但關心水在不在,還要在你離開的時候水被人動過沒有,因為你是程序員,所以就想起了放了張紙在旁邊,寫上初始值0,別人喝水前麻煩先做個累加才能喝水。這就是AtomicStampedReference的解決方案。

  • 我寫了個代碼,大家請看
import java.util.concurrent.atomic.AtomicStampedReference;
public class AtomicStampedReferenceTest { static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference(0, 0); public static void main(String[] args) throws InterruptedException { final int stamp = atomicStampedReference.getStamp(); final Integer reference = atomicStampedReference.getReference(); System.out.println(reference+"============"+stamp); Thread t1 = new Thread(new Runnable() { @Override public void run() { System.out.println(reference + "-" + stamp + "-" + atomicStampedReference.compareAndSet(reference, reference + 10, stamp, stamp + 1)); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { Integer reference = atomicStampedReference.getReference(); System.out.println(reference + "-" + stamp + "-" + atomicStampedReference.compareAndSet(reference, reference + 10, stamp, stamp + 1)); } }); t1.start(); t1.join(); t2.start(); t2.join(); System.out.println(atomicStampedReference.getReference()); System.out.println(atomicStampedReference.getStamp()); } }

輸出結果:

0============0 0-0-true 10-0-false 10 1

結論:可以看出第二次更新的時候,失敗了,因為版本號已經被改變了,所以AtomicStampedReference幫我們解決了CAS操作中的ABA問題!

AtomicMarkableReference跟AtomicStampedReference差不多, 
AtomicStampedReference是使用pair的int stamp作為計數器使用,AtomicMarkableReference的pair使用的是boolean mark。 
還是那個水的例子,AtomicStampedReference可能關心的是動過幾次,AtomicMarkableReference關心的是有沒有被人動過,方法都比較簡單。


免責聲明!

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



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