Java多线程之CAS缺点
生活随笔
收集整理的這篇文章主要介紹了
Java多线程之CAS缺点
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Java多線程之CAS缺點
目錄:
1. 循環時間開銷很大
通過看源碼,我們發現有個do while,如果CAS失敗,會一直進行嘗試。如果CAS長時間一直不成功,可能會給CPU帶來很大的開銷。
2. 只能保證一個共享變量的原子操作
當對一個共享變量執行操作時,我們可以使用循環CAS的方式來保證原子操作。但是,對多個共享變量操作時,循環CAS就無法保證操作的原子性,這個時候就可用鎖來保證原子性。
3. 引來ABA問題及解決方案(重點)
1.ABA問題概述
2. 原子引用
解決ABA問題只靠CAS不能解決,還需要用到原子引用技術。即AtomicReference
簡單代碼測試
import lombok.AllArgsConstructor; import lombok.Getter; import lombok.ToString;import java.util.concurrent.atomic.AtomicReference;@Getter @ToString @AllArgsConstructor class User{String userName;int age; } public class AtomicReferenceDemo {public static void main(String[] args) {User z3 = new User("Z3",22);User li4 = new User("li4",25);AtomicReference<User> atomicReference = new AtomicReference<>();atomicReference.set(z3);System.out.println(atomicReference.compareAndSet(z3, li4)+"\t"+atomicReference.get().toString());System.out.println(atomicReference.compareAndSet(z3, li4)+"\t"+atomicReference.get().toString());} }編譯結果
3. ABA問題解決方案
解決: 原子引用+修改版本號(類似時間戳)
代碼:
import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicStampedReference;/*** ABA問題的解決: AtomicStampedReference*/ public class ABADemo {static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1);public static void main(String[] args) {System.out.println("=============以下是ABA問題的產生==============");new Thread(() -> {atomicReference.compareAndSet(100, 101);atomicReference.compareAndSet(101, 100);}, "t1").start();new Thread(() -> {try {//暫停一秒鐘,保證上面的t1完成了一次ABA操作TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(atomicReference.compareAndSet(100, 2019)+ "\t" + atomicReference.get());}, "t2").start();//暫停兩秒鐘等上面代碼執行完try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("=============以下是ABA問題的解決==============");new Thread(() -> {int stamp = atomicStampedReference.getStamp();System.out.println(Thread.currentThread().getName() + "\t第一次版本號" + stamp);// 暫停一秒鐘t3線程,為了t4線程也能拿到相同的stamp。try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}atomicStampedReference.compareAndSet(100, 101,atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);System.out.println(Thread.currentThread().getName() + "\t第2次版本號" + atomicStampedReference.getStamp());atomicStampedReference.compareAndSet(101, 100,atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);System.out.println(Thread.currentThread().getName() + "\t第2次版本號" + atomicStampedReference.getStamp());}, "t3").start();new Thread(() -> {int stamp = atomicStampedReference.getStamp();System.out.println(Thread.currentThread().getName() + "\t第一次版本號" + stamp);// 暫停3秒鐘t4線程,保證上面的t3線程完成了一次ABA操作。try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}boolean result = atomicStampedReference.compareAndSet(100, 101, stamp, stamp + 1);System.out.println(Thread.currentThread().getName() + "\t修改成功否:" + result+ "\t當前最新實際版本號:" + atomicStampedReference.getStamp());System.out.println(Thread.currentThread().getName() + "\t當前實際最新值" + atomicStampedReference.getReference());}, "t4").start();} }編譯結果:
總結
以上是生活随笔為你收集整理的Java多线程之CAS缺点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java多线程之CAS深入解析
- 下一篇: Java锁之公平和非公平锁