1. 程式人生 > 實用技巧 >Java-學習日記(Atomic,Volatile)

Java-學習日記(Atomic,Volatile)

很早之前在公司就看到了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標記更新次數,若沒被更新,則正確,否則報錯。

面試問題:併發程式設計(原子性、可見性、一致性)