10.22 解決CAS機制中ABA問題的AtomicStampedReference詳解

AtomicStampedReference是一個帶有時間戳的對象引用,能很好的解決CAS機制中的ABA問題,這篇文章將通過案例對其介紹分析。

一、ABA問題

ABA問題是CAS機制中出現的一個問題,他的描述是這樣的。我們直接畫一張圖來演示,

解決CAS機制中ABA問題的AtomicStampedReference詳解

什麼意思呢?就是說一個線程把數據A變為了B,然後又重新變成了A。此時另外一個線程讀取的時候,發現A沒有變化,就誤以為是原來的那個A。這就是有名的ABA問題。ABA問題會帶來什麼後果呢?我們舉個例子。

一個小偷,把別人家的錢偷了之後又還了回來,還是原來的錢嗎,你老婆出軌之後又回來,還是原來的老婆嘛?ABA問題也一樣,如果不好好解決就會帶來大量的問題。最常見的就是資金問題,也就是別人如果挪用了你的錢,在你發現之前又還了回來。但是別人卻已經觸犯了法律。

如何去解決這個ABA問題呢,就是使用今天所說的AtomicStampedReference。

二、AtomicStampedReference

1、問題解決

我們先給出一個ABA的例子,對ABA問題進行場景重現。

解決CAS機制中ABA問題的AtomicStampedReference詳解

在上面的代碼中,我們使用張三線程,對index10->11->10的變化,然後李四線程讀取index觀察是否有變化,並設置新值。運行一下看看結果:

解決CAS機制中ABA問題的AtomicStampedReference詳解

這個案例重現了ABA的問題場景,下面我們看如何使用AtomicStampedReference解決這個問題的。

解決CAS機制中ABA問題的AtomicStampedReference詳解


解決CAS機制中ABA問題的AtomicStampedReference詳解

上面的代碼我們再來分析一下,我們會發現AtomicStampedReference裡面增加了一個時間戳,也就是說每一次修改只需要設置不同的版本好即可。我們先運行一邊看看:

解決CAS機制中ABA問題的AtomicStampedReference詳解

這裡使用的是AtomicStampedReference的compareAndSet函數,這裡面有四個參數:

compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp)。

(1)第一個參數expectedReference:表示預期值。

(2)第二個參數newReference:表示要更新的值。

(3)第三個參數expectedStamp:表示預期的時間戳。

(4)第四個參數newStamp:表示要更新的時間戳。

這個compareAndSet方法到底是如何實現的,我們深入到源碼中看看。

2、源碼分析

解決CAS機制中ABA問題的AtomicStampedReference詳解

剛剛這四個參數的意思已經說了,我們主要關注的就是實現,首先我們看到的就是這個Pair,因此想要弄清楚,我們再看看這個Pair是什麼,

解決CAS機制中ABA問題的AtomicStampedReference詳解

在這裡我們會發現Pair裡面只是包存了值reference和時間戳stamp。

在compareAndSet方法中最後還調用了casPair方法,從名字就可以看到,主要是使用CAS機制更新新的值reference和時間戳stamp。我們可以進入這個方法中看看。

解決CAS機制中ABA問題的AtomicStampedReference詳解

​三、總結

其實除了AtomicStampedReference類,還有一個原子類也可以解決,就是AtomicMarkableReference,它不是維護一個版本號,而是維護一個boolean類型的標記,用法沒有AtomicStampedReference靈活。因此也只是在特定的場景下使用。

解決CAS機制中ABA問題的AtomicStampedReference詳解


分享到:


相關文章: