Java-學習日記(Atomic,Volatile)
阿新 • • 發佈:2020-09-21
很早之前在公司就看到了atomicInteger,atomicLong這些變量了,一直不明白是什麼意思,今天花了點時間瞭解下。
volatile:
先從volatile開始講起,volatile是多執行緒中會使用的關鍵字,volatile不加鎖(即不會執行緒阻塞,但不安全),但保證了可見性(一個執行緒修改,立即重新整理到主記憶體,對其他執行緒可見)和禁止指令重排序。但是這樣依然對存在一個問題,就是多執行緒時候來不及重新整理到主記憶體中,新執行緒就獲取到了舊資料。例如下面程式碼:
錯誤原因:有的執行緒已經把a進行了加1操作,但是還沒來得及重新刷入到主存,其他的執行緒就重新讀取了舊值。因為才造成了錯誤
package atomic; import java.util.concurrent.atomic.AtomicInteger; /** * @ProjectName: AtomicIntegerTest * @Package: atomic * @Description: * @Author: huyuqiao * @CreateDate: 2020/9/21 14:25 */ //Volatile:無法保證最後a結果一定是50 //AtomicInteger:雖然最後順序不一樣,但是最終a一定是50 public class AtomicIntegerTest { // private static volatile int a = 0; static AtomicInteger a = new AtomicInteger(); public static void main(String[] args){ AtomicIntegerTest atomicIntegerTest = new AtomicIntegerTest(); Thread[] threads = new Thread[5]; for (int i = 0; i < 5; i++) { threads[i] = new Thread(() ->{ try{ for (int i1 = 0; i1 < 10; i1++) { // System.out.println(a++); System.out.println(a.incrementAndGet()); Thread.sleep(500); } } catch (Exception e){ e.printStackTrace(); } }); threads[i].start(); } } }
atomicInteger
上面程式碼中atomicInteger卻保證了資料的完整性,原因就在於內部CAS原理(compare and swap)
CAS 即比較並替換,實現併發演算法時常用到的一種技術。CAS操作包含三個運算元——記憶體位置、預期原值及新值。執行CAS操作的時候,將記憶體位置的值與預期原值比較,如果相匹配,那麼處理器會自動將該位置值更新為新值,否則,處理器不做任何操作。
但是這樣會有一個ABA問題,就是雖然你保證了資料最終一定一直,但是無法保證資料中途會被修改,即ABA問題(變數A->B->A中途會被修改)
ABA問題解決辦法:解決使用AtomicStampReference.getstamp標記更新次數,若沒被更新,則正確,否則報錯。
面試問題:併發程式設計(原子性、可見性、一致性)