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
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