JUC - 02 关于java.util.concurrent.atomic包

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

你可能感兴趣的:(java,JUC,并发,多线程)