1. 程式人生 > 程式設計 >1.2.2 執行緒安全之原子操作

1.2.2 執行緒安全之原子操作

競態條件與臨界區

共享資源

不可變物件

原子操作定義

  • 原子操作可以是一個步驟,也可以是多個操作步驟,但是其順序不可以被打亂,也不可以被切割而只執行其中的一部分(不可中斷性)。
  • 將整個操作視作一個整體,資源在該次操作中保持一致,這是原子性的核心特徵。

CAS機制

	volatile int value = 0;

    static Unsafe unsafe; // 直接操作記憶體,修改物件,陣列記憶體....強大的API
    private static long valueOffset;

    static {
        try {
            // 反射技術獲取unsafe值
Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); unsafe = (Unsafe) field.get(null); // 獲取到 value 屬性偏移量(用於定於value屬性在記憶體中的具體地址) valueOffset = unsafe.objectFieldOffset(LockDemo1.class .getDeclaredField("value"
)); } catch (Exception ex) { ex.printStackTrace(); } } public void add() { // TODO xx00 // i++;// JAVA 層面三個步驟 // CAS + 迴圈 重試 int current; do { // 操作耗時的話, 那麼 執行緒就會佔用大量的CPU執行時間 current = unsafe.getIntVolatile(this
,valueOffset); } while (!unsafe.compareAndSwapInt(this,valueOffset,current,current + 1)); // (可能會失敗)CAS命令,如果current值發生變化,則操作失敗 } 複製程式碼
  • 有興趣的童鞋可以瞭解下Unsafe的原始碼,類似於直接操作記憶體的方法。JVM呼叫系統本地方法操作資料,保證只有一個執行緒可以訪問到本地方法操作,實現原子操作。

J.U.C包內的原子操作封裝類

  • java.until.concurrent執行緒工具類(J.U.C)

CAS的三個問題

  • JAVA提供了ABA的解決辦法:原子更新帶有版本號的引用型別。CAS在比對是不僅比對值,還會比對版本號。
  • Atomic原子操作封裝類,將i++分成了幾步(讀取值,更新值,賦值),使用了底層的CAS機制,並且不僅僅存了值,還存了時間戳版本號。