美文网首页
CAS的原理

CAS的原理

作者: baifanger | 来源:发表于2020-11-03 00:35 被阅读0次

    1.什么是CAS
    CAS: CompareAndSwap,是一种实现锁的机制。
    我们知道,在jdk 1.5之前,一般我们都会用synchronized来保证同步的,但这种锁存在以下几种问题:

    • 在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。(什么是上下文切换)
    • 一个线程持有锁会导致其它所有需要此锁的线程挂起。
    • 如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险

    而CAS则类似于一种乐观锁,利用cpu的cas原子操作指令,借助于native进行调用,达到锁的目的。这是一种非阻塞算法,此过程无需上下文的切换,相对于synchronized来说,极大的提高了性能

    2.cas的实现原理
    CAS,在有的地方,我们称之为自旋锁。在JDK 1.5之后,在java.util.concurrent.atomic提供了一系列的原子操和类。其基本思想就是:拿着现有的值,计算出期望值,并交由cas处理,通过比较来得出期望值是否正确,如果不正确,则刷新现有的值,不停的循环计算。

    image.png
     AtomicInteger.java
        public final int updateAndGet(IntUnaryOperator updateFunction) {
            int prev, next;
            do {
                prev = get();
                next = updateFunction.applyAsInt(prev);
            } while (!compareAndSet(prev, next));
            return next;
        }
        public final boolean compareAndSet(int expect, int update) {
            return U.compareAndSwapInt(this, VALUE, expect, update);
        }
    
    Unsafe.java
        public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
    
        public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
    
        public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
    
    

    从上述图和代码中可以看到,cas指令的原子性保证了结果的正确性,同时,由于有可能结果不正确,所以会出现不停的在做while循环的情况,这也是 cas被称为自旋锁的原因

    3.cas存在的问题

    • ABA问题
          假设 thread1和thread2要操作某个对象,该对象值为A. thread1的目的是将A变成B. 当thread1拿到值为A后,由于时间片轮转原因,调度到了thread2,而Thread2拿到A后,将值由A变成了B,又由B改回了A。cpu此时再度调度到thread1,将A改成了B,经过compareAndSet计算后,结果正确,更改成功。
          这就是ABA问题,虽然A在经过thread2处理后,值并没有变化,但实际上它是变化过的,但cas并不能检测出这个问题的存在。
          解决方法,其实我们如果自己写的话,可以增加个version之类的变量,来辅助完成比较,而concurrent包中的AtomicMarkableReference、AtomicStampedReference也能解决此问题。
    • 开销问题
          由于自旋的存在,在极端情况下,会出现一直在不停的while循环的情况,这也是无法避免的
    • 只能保证一个共享变量的操作
          通过查看AtmoicXXX的各种实现类,我们可以发现,原子操作只能针对一个变量,无法针对多个变量或代码块来进行,当然,利用AtomicReference可以间接的来实现多个变量的操作,但这个不能从架构甚至需求上完美的解决问题,这也是synchronized为何性能较差但还至今存在重要原因之一。

    相关文章

      网友评论

          本文标题:CAS的原理

          本文链接:https://www.haomeiwen.com/subject/yvduvktx.html