多線程之CAS與synchronized的比較


業務場景:需要實現一個支持並發的計數功能

1、計數功能的基本實現是:

public class  Increment{

  private int count = 0;

  public void add(){   count++;   }

}

2、以上實現在並發環境下是不安全的,故修改方案1是加鎖synchronized

public class  Increment{

  private int count = 0;

  public synchronized  void add(){   count++;   }

}

//悲觀鎖,加鎖后只能有一個線程你執行++操作,其他線程需要等待

//不會出現count計數不准確的問題,線程安全

3、但是以上實現,會讓線程串行化,排隊等待獲取鎖、加鎖、處理數據、釋放鎖,並發下顯得不合理

修改方案2是使用Java並發包concurrent下的Atomic原子類

public class  Increment{

  private AtomicInteger count = new AtomicInteger();

  public synchronized void add(){

    count.incrementAndGet();

  }

}

//多個線程可以並發的執行AtomicInteger的incrementAndGet()方法,把count的值累加1並返回累加后最新的值

//Atomic原子類底層用的是無鎖化的CAS機制,保證多線程修改一個數值的安全性

4、實現原理:

(1)每個線程都會先獲取當前的值,接着走一個原子的CAS操作,原子的意思就是這個CAS操作一定是自己完整執行完的,不會被別人打斷;

(2)在CAS操作里,比較一下,現在的值跟剛才我獲取到的那個值,是否相等,是則說明沒有人改過這個值,那么將它設置成累加1之后的一個值;

(3)同理,若有人在執行CAS時,發現自己之前獲取的值與當前的值不一樣,說明有其他人修改了值,導致CAS失敗,失敗之后進入一個循環,再次獲取值,再執行CAS操作。

5、CAS的問題

每次去比較的時候,都發現值被別人改了,就會進入無限重復的循環。大量線程高並發時相當於空循環,自旋轉,性能和效率都不是特別好。

Java8的新類LongAdder,嘗試使用分段CAS以及自動分段遷移的方式來提升多線程高並發執行CAS操作的性能。核心思想是熱點分離,類似concurrentHashMap


免責聲明!

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



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