AtomicReference
演示实例
public class AtmoicExample {
private static AtomicReference<Integer> atomicReference=new AtomicReference<>(0);
public static void main(String[] args) {
atomicReference.compareAndSet(0,2);//0
atomicReference.compareAndSet(0,1);//不执行
atomicReference.compareAndSet(1,3);//不执行
atomicReference.compareAndSet(2,4);//4
atomicReference.compareAndSet(3,5);//不执行
System.out.println("count:"+atomicReference.get());
}
}
执行结果:count:4
注:以一行为0时,更新为2,第二、三行都不为2所以不执行,第四行为2,故更新为4,最后一行不执行
AtomicReferenceFiledUpdater
演示实例
private static AtomicIntegerFieldUpdater<AtmoicExample2> updater=AtomicIntegerFieldUpdater.newUpdater(AtmoicExample2.class,"count");
public int getCount() {
return count;
}
private volatile int count=100;
public static AtmoicExample2 example2=new AtmoicExample2();
public static void main(String[] args) {
if(updater.compareAndSet(example2,100,120)){
System.out.println("updater success:"+example2.getCount());
}
if(updater.compareAndSet(example2,100,120)){
System.out.println("updater success 1:"+example2.getCount());
}
else{
System.out.println("updater fail 1:"+example2.getCount());
}
}
注:实例化AtomicReferenceFiledUpdater,AtomicIntegerFieldUpdater.newUpdater(AtmoicExample2.class,"");第一个参数是这个类对应的class,第二个参数是对应的字段名称,需要先定义一个字段,必须用volatile修饰,实现get方法,compareAndSet,第一个参数是当前类变量,如果该值是100的时候更新为120,这个类AtomicReferenceFiledUpdater核心是原子性更新某个类的实例的某个字段,这个字段必须是volatile修饰,同时还不能是static字段
AtomicStampReference:解决CAS的ABA问题
什么事ABA问题
在CAS操作的时候,其它线程将变量的值A改回了B又改回了A,本线程使用期望值A与当前线程进行比较的时候发现A变量没有变,于是CAS就将A值进行了交换操作,这个时候,其实该值已经被其它线程改变过,以至于与CAS思想不符合,ABA问题解决思路
每次变量更新的时候,将变量的版本号加1,那么之前的A改为B在改回A,就变成了A对应的1版本改为B变为2版本在改回A变为3版本,只要变量被修改过那么该变量的版本号就回递增发生变化,从而解决了ABA问题
相关源码如下:
/**
* Atomically sets the value of both the reference and stamp
* to the given update values if the
* current reference is {@code ==} to the expected reference
* and the current stamp is equal to the expected stamp.
*
* @param expectedReference the expected value of the reference
* @param newReference the new value for the reference
* @param expectedStamp the expected value of the stamp
* @param newStamp the new value for the stamp
* @return {@code true} if successful
*/
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
expectedStamp == current.stamp &&
((newReference == current.reference &&
newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp)));
}
注:这个方法对比其他compareAndSet方法的比较多了一个stamp的比较,stamp的值是由每次更新的时候来维护的,它的使用和其它atomic包类似
AtomicLongArray
定义:比AomicLong多了一个Array,维护了一个数组,选择性的更新某一个索引的值,也是进行原子性操作的,比起AtomicLong多了一个索引的方法让我们更新
相关源码
/**
* Atomically sets the element at position {@code i} to the given value
* and returns the old value.
*
* @param i the index
* @param newValue the new value
* @return the previous value
*/
public final long getAndSet(int i, long newValue) {
return unsafe.getAndSetLong(array, checkedByteOffset(i), newValue);
}
/**
* Atomically sets the element at position {@code i} to the given
* updated value if the current value {@code ==} the expected value.
*
* @param i the index
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int i, long expect, long update) {
return compareAndSetRaw(checkedByteOffset(i), expect, update);
}
注:参数取出对应的索引,更新一个值,compareAndSet:取出对应的索引,期望值,和更新值仅此而已