Boolean/Integer/Long/Array
compareAndSet(boolean expect, boolean update)。
这个方法主要两个作用
1. 比较AtomicBoolean和expect的值,如果一致,执行方法内的语句。其实就是一个if语句
2. 把AtomicBoolean的值设成update
比较最要的是这两件事是一气呵成的,这连个动作之间不会被打断,任何内部或者外部的语句都不可能在两个动作之间运行。为多线程的控制提供了解决的方案。
public final boolean getAndSet(boolean newValue)
以原子方式设置为给定值,并返回以前的值。
public booleanweakCompareAndSet(boolean expect,
boolean update)
如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
可能意外失败并且不提供排序保证,因此几乎只是 compareAndSet 的适当替代方法。
void lazySet(boolean newValue)
最终会设置成newValue,使用lazySet设置值后,可能导致其他线程在之后的一小段时间内还是可以读到旧的值。
AtomicIntegerFieldUpdater/AtomicLongFieldUpdater
基于反射的实用工具,可以对指定类的指定 volatile int
字段进行原子更新。此类用于原子数据结构,该结构中同一节点的几个字段都独立受原子更新控制。
public static <U>AtomicIntegerFieldUpdater<U>newUpdater(Class<U> tclass,
String fieldName)
使用给定字段为对象创建和返回一个更新器。需要 Class 参数来检查反射类型和一般类型是否匹配。
AtomicStampedReference/AtomicMarkableReference
cas的ABA问题就是 假设初始值为A,线程3和线程1都获取到了初始值A,然后线程1将A改为了B,线程2将B又改回了A,这时候线程3做修改时,是感知不到这个值从A改为了B又改回了A的过程:
AtomicStampedReference 本质是有一个int 值作为版本号,每次更改前先取到这个int值的版本号,等到修改的时候,比较当前版本号与当前线程持有的版本号是否一致,如果一致,则进行修改,并将版本号+1(当然加多少或减多少都是可以自己定义的),在zookeeper中保持数据的一致性也是用的这种方式;
AtomicMarkableReference则是将一个boolean值作是否有更改的标记,本质就是它的版本号只有两个,true和false,修改的时候在这两个版本号之间来回切换,这样做并不能解决ABA的问题,只是会降低ABA问题发生的几率而已;