• CAS是个什么鬼?


    cas(CompareAndSet)号称无锁优化,或者叫自旋,也被叫做乐观锁。这个名字无所谓,重要的是这个东西是做什么的。

    由于某一些特别常见的操作,老是来回的加锁,加锁的情况特别多,所以java就直接提供了这些常见的操作,也就是以Atomic开头的类,这些类的内部就自动带了锁,当然这些锁的实现并不是synchronize重量级锁,而是CAS的操作来实现的。(号称无锁)

    凡是以Atomic开头的都是用CAS这种操作来保证线程安全的这么一些个类。AtomicInteger的意思就是里面包了一个Int类型,这个int类型的自增count++是线程安全的,还有拿值等等是线程安全的,由于我们在工作中开发中经常性的有那种需求,一个值所有的线程共同访问它往上递增,所以jdk专门提供了这样的一些类。

    ·Atomxxx类的本身方法是原子性的,但不能保证多个方法连续调用都是原子性的。

        public final int incrementAndGet() {
            return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
        }
    @HotSportIntrinscCandidate
    public final int getAndAddInt(Object o,long offset,int delta){
        int v;
        do{
            v=getIntVolatile(o,offset);
           }while(!weakCompareAndSetInt(o,offset,v,v+delta));
            return v;               
    }   

    它内部调用的过程中就跑去了Unsafe类去了。也就是说AtomicInteger的内部调用了UnSafe这个类里面的方法CompareAndSetl(CAS)。

    cas方法简单的理解的话,可以看成是

    cas(V,Expected,NewValue)

    V表示的是目前的值,也就是要改的值,Expected表示的是期望值,期望值就是你觉得他现在应该是多少,NewValue就是更新后的值。

    如果V和Expected的值不一致的话,那么此次值变更操作将失败,说明其他线程改了这个值。那么你就可以再试一遍或者失败,这就是cas操作。

    当你判断的时候发现是你的期望值,还没进行新值设定的时候,发生了改变怎么办,cas是CPU的原语支持,也就是说cas操作是cpu指令级别的操作,中间不能被打断。

    ABA问题:

    假如说你有一个值,我拿到的这个值是1,想把它变成2,我拿到1用cas操作,期望值是1,准备变成2,这个对象Object,在这个过程中,没有一个线程改过我肯定是可以更改的额,但是如果有一个线程在这期间把1改成了2,又改成了1,中间的值变过了,它不会影响我这个cas操作,这就是ABA问题。

    这种问题的解决办法就是追加版本号,该每一次操作都追加一次修改版本号,确认期望值的时候一起确认值对应的版本号就可以了。

    *CAS操作数值不需要加锁的原因是使用了Unsafe类。

  • 相关阅读:
    [设计模式] 10 外观模式 facade
    [设计模式] 11 享元模式 Flyweight
    [设计模式] 9 装饰者模式 Decorator
    [设计模式] 8 组合模式 Composite
    float2int
    《ASP.NET》数据绑定——GridView
    Android Studio左边栏Project不见了?
    Linux下的五种I/O模型
    Shell编程入门(第二版)(下)
    Android訪问网络,使用HttpURLConnection还是HttpClient?
  • 原文地址:https://www.cnblogs.com/SpaceKiller/p/12611334.html
Copyright © 2020-2023  润新知