Aomic數據類型有四種類型:AomicBoolean, AomicInteger, AomicLong, 和AomicReferrence(針對Object的)以及它們的數組類型,
還有一個特殊的AomicStampedReferrence,它不是AomicReferrence的子類,而是利用AomicReferrence實現的一個儲存引用和Integer組的擴展類
首先,所有原子操作都是依賴於sun.misc.Unsafe這個類,這個類底層是由C++實現的,利用指針來實現數據操作
關於CAS
一種無鎖機制,比較並交換, 操作包含三個操作數 —— 內存位置(V)、預期原值(A)和新值(B)。如果內存位置的值與預期原值相匹配,那麼處理器會自動將該位置值更新為新值。否則,處理器不做任何操作。無 論哪種情況,它都會在 CAS 指令之前返回該位置的值。CAS 有效地說明了“我認為位置 V 應該包含值 A;如果包含該值,則將 B 放到這個位置;否則,不要更改該位置,只告訴我這個位置現在的值即可”
好處:操作系統級別的支持,效率更高,無鎖機制,降低線程的等待,實際上是把這個任務丟給了操作系統來做。
這個理論是整個java.util.concurrent包的基礎。
關於sun.misc.Unsafe
幾個疑問
1)四個基本類型的compareAndSet和weakCompareAndSet實現是一樣的?
2)AtomicLong的set方法非線程安全的,為啥?並非線程不全,而是對於Long的Updater,會有VM_SUPPORTS_LONG_CAS,如果JVM的long操作是原子化的,會采用無鎖的CAS來更新,如果不支持就會使用帶鎖的方式來更新。
AtomicXXXX四個數值類型
1. value成員都是volatile
2. 基本方法get/set
3. compareAndSet
weakCompareAndSet,
lazySet: 使用Unsafe按照順序更新參考Unsafe的C++實現)
getAndSet:取當前值,使用當前值和准備更新的值做CAS
4. 對於Long和Integer
getAndIncrement/incrementAndGet
getAndDecrement/decrementAndGet
getAndAdd/addAndGet
三組方法都和getAndSet,取當前值,加減之得到准備更新的值,再做CAS,/左右的區別在於返回的是當前值還是更新值。
關於數組
1. 沒有Boolean的Array,可以用Integer代替,底層實現完全一致,畢竟AtomicBoolean底層就是用Integer實現
2. 數組變量volatile沒有意義,因此set/get就需要Unsafe來做了,方法構成與上面一致,但是多了一個index來指定操作數組中的哪一個元素。
關於FieldUpdater
1) 利用反射原理,實現對一個類的某個字段的原子化更新,該字段類型必須和Updater要求的一致,例如如果使用 AtomicIntegerFieldUpdater,字段必須是Integer類型,而且必須有volatile限定符。Updater的可以調用的方 法和數字類型完全一致,額外增加一個該類型的對象為參數,updater就會更新該對象的那個字段了。
2) Updater本身為抽象類,但有一個私有化的實現,利用門面模式,在抽象類中使用靜態方法創建實現
AtomicMarkableReference/AtomicStampedReference
前者ReferenceBooleanPair類型的AtomicReference,ReferenceBooleanPair表示一個對象和boolean標記的pair
前者ReferenceIntegerPair類型的AtomicReference,ReferenceBooleanPair表示一個對象和Integer標記的pair
作者:cnblogs 梧留柒