CAS 的比較置換動作雖然是原子性操作,但是當獲得了物件當前值後,在比較期望值與剛取出的當前值前,這個物件被其他執行緒連續修改兩次,經過這兩次修改後,物件又恢復為舊值。這樣一來我們就無法透過 CAS 來確認這個物件是否被修改過。
假設 compareAndSwap(實際值, 期望值, 新值)
步驟 | Thread-1 | Thread-2 |
---|---|---|
1 | 取出實際值 x=1 | 取出實際值 x=1 |
2 | compareAndSwap(實際值, x, 2):實際值變為 2 | |
3 | compareAndSwap(實際值, x, 1):實際值變為 1 | |
4 | compareAndSwap(實際值, x, 2):實際值變為 2 |
上面了例子就說明了這個情況,既使 Thread-2 修改過值 2 次,Thread-1 中的 CAS 也發現不了衝突。
要想解決這個問題,可以給 CAS 加上一個時間戳記,這個時間戳記是永遠正向增長的。CAS 時也會比較這個時間戳。事務上 AtomicStampedReference 就有使用到這個概念,下一個章節就會提到。