三.Atomic原子类实现CAS语义

AtomicInteger

AtomicInteger是一个原子的自增操作类

分析一下AtomicInteger的源码

先看看它的成员变量

private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
private volatile int value;

Unsafe类是jdk内部使用的类,和硬件打交道用来做cas原子性操作的

value是自增的变量

valueOffset是value这个变量在这个类的偏移量位置,通过cas操作修改偏移量

 

 

 

看看getAndIncrement方法源码

 

public final int getAndIncrement() {
    return unsafe.getAndAddInt(this, valueOffset, 1);
}

内部调用unsafe类的getAndAddInt方法

public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

    return var5;
}

 

一个do-while循环,getIntVolatile是一个native方法,获取当前对象里面value的偏移量的值

然后调用compareAndSwapInt方法,compareAndSwapInt先比较再修改,这就是cas操作,cas成功返回ture,失败返回false,var1是当前对象this,var2是原来value的偏移量,var5是原来value的值,var5+var4,是值,cas操作会锁定一块内存,先比较是不是原来的值,如果是就修改,如果不是是返回false,如果false就会进入下一次循环知道修改成功为止

 

Atomic原子类CAS的缺点

1.ABA问题:某个值一开始是A,后来变成B,然后又变成了A,比较的时候发现还是A,但是其实被修改过,atomic包里有AtomicStampedReference类,就是会比较两个值的引用是否一致,如果一致,才会设置新值

2.无限循环问题:并非冲突过高的,一直修改失败无限循环重试,导致循环很多次才能成功,JDK1.8里面引入LongAddr来解决,分段CAS思路

3.多变量原子问题:AtomicInterger只能保证一个变量的原子性,多个变量原子性可以用AtomicReference来保证,这个类封装自定义对象,检查这个对象的引用是不是同一个

 

LongAddr

为了避免大量并发对一个值修改导致大量失败重试,把值拆成多个cell,先对一个cell做cas操作,如果发现自选次数太多就会换到另一个cell做cas操作,最后把所有cell的值加起来就是最后的结果了,比如要从0自增,10个cell,每个cell自增了5次,然后所有cell加起来就是最后的结果50了,默认是两个cell,每次cell扩大是翻倍,下图表示

 

 

 

AtomicReference

AtomicReference是解决多个属性的cas操作的,AtomicReference可以传一个自定义的对象,每次判断引用还是不是之前的那个

 

public final boolean compareAndSet(V expect, V update) {
    return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}

public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

通过unsafe.compareAndSwapObject方法,新值和就值的引用还是不是同一个,是就修改成功,不是就返回失败

 

AtomicStampedReference

AtomicStampedReference是解决aba问题,加了版本号的机制

里面多了一个stamp,每次cas的时候都会比较久值 还会比较版本号是不是一样,不一样就算失败

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值