线程安全性--原子性---atomic(2)

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:取出对应的索引,期望值,和更新值仅此而已

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值