Atomic XXX 的原子操作

volitale 關鍵字他是不具備原子性的,但是Atomic XXX 都是具備原子性操作

public static void main(String[] args) {
       //AtomicInteger
       AtomicInteger atomicInteger = new AtomicInteger();
       System.out.println(atomicInteger.get()); // 結果 0
       atomicInteger = new AtomicInteger(10);
       System.out.println(atomicInteger.get()); // 10
       atomicInteger.set(20);
       System.out.println(atomicInteger.get()); // 20

       int sum = atomicInteger.getAndAdd(30);
       System.out.println(sum); // 20
       System.out.println(atomicInteger.get()); // 通過get菜可以得到值

       //AtomicBoolean AtomicLong .. 等等都和上面使用差不多

   }

AtomicReference
包裝對象爲原子性操作

CAS 會引起 ABA問題

摘抄自:https://www.cnblogs.com/androidsuperman/p/9249180.html
CAS需要在操作值的時候檢查下值有沒有發生變化,如果沒有發生變化則更新,但是如果一個值原來是A,變成了B,又變成了A,那麼使用CAS進行檢查時會發現它的值沒有發生變化,但是實際上卻變化了。ABA問題的解決思路就是使用版本號。在變量前面追加上版本號,每次變量更新的時候把版本號加一,那麼A-B-A 就會變成1A-2B-3A。 從Java1.5開始JDK的atomic包裏提供了一個類AtomicStampedReference來解決ABA問題。這個類的compareAndSet方法作用是首先檢查當前引用是否等於預期引用,並且當前標誌是否等於預期標誌,如果全部相等,則以原子方式將該引用和該標誌的值設置爲給定的更新值。

AtomicStampedReference<Integer> stampedReference = new AtomicStampedReference<>(100,0); stampedReference.compareAndSet(100,0,stampedReference.getStamp(),stampedReference.getStamp()+1);

下面 AtomicIntegerArray、 AtomicLongArray、 AtomicReferenceArray 效果和用法等同於上面

AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater
對操作對象添加原子性操作

public class Test {

    public static void main(String[] args) {
        // 這個操作,會對age屬性添加原子性操作
        final AtomicIntegerFieldUpdater fieldUpdater = AtomicIntegerFieldUpdater.newUpdater(Student.class,"age");
        Student student = new Student();
        fieldUpdater.compareAndSet(student,0,1);
        // 上面這個操作需注意,可能會出現以下錯誤
        /**
         * 1,privateFieldAccessError // 屬性私有化
         * 2,TargetObjectIsNull  // student 換成null 報這個錯誤
         * 3,fieldNameInvalid
         */
    }
}

@Data
class Student{

    volatile int age;
}

unsafe 類圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章