juc学习二(CAS底层原理)

Posted mabaoying

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了juc学习二(CAS底层原理)相关的知识,希望对你有一定的参考价值。

讲解线路:

CAS-->UnSafe-->CAS底层思想-->ABA-->原子引用更新-->如何规避ABA问题

CAS是什么

CAS的全称为Compare-And-Swap,即比较并交换,它是一条CPU并发原语。它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的。

CAS并发原语体现在JAVA语言中就是sun.misc.Unsafe类中的各个方法。调用UnSafe类中的CAS方法,JVM会帮我们实现出CAS汇编指令。这是一种完全依赖于硬件的功能,通过它实现了原子操作。再次强调,由于CAS是一种系统原语,原语属于操作系统用语范畴,是由若干条指令组成的,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致问题。

我们先来看看AtomicInteger源码,我们知道了AtomicInteger原子变量通过了用volatile修饰变量保证内存可见性,CAS(Compare-And-Swap)算法保证数据的原子性。

技术图片

 

 我们看AtomicInteger中的getAndIncrement方法,其作用相当于i++,先取i的值,再自增一。它能在多线程的环境下保持数据原子性。它调用了UnSafe类的CompareAndSwapInt方法,this为当前AtomicInteger对象,valueOffeset为该变量值在内存中的偏移地址,因为UnSafe就是通过内存偏移地址获取数据。

 技术图片

 

var5为当前对象和内存偏移地址就可以获取当前物理内存值作为副本,然后再判断内存值与预期值,相等值加一,修改成功则跳出循环,否则一直自旋。

 技术图片

 

Unsafe类是CAS的核心类,由于java方法无法直接访问底层系统,需要通过本地(native)方法来访问,Unsafe相当于一个后门吧,基于该类可以直接操作特定内存的数据。Unsafe类存在于sun.misc包中,其内部方法操作可以像C的指针一样直接操作内存,因为java中CAS操作的执行依赖于Unsafe类的方法。CAS底层靠的是Unsafe这个类来保证原子性。

注意:Unsafe类中的所有方法都是native修饰的,也就是说Unsafe类中的方法都是直接调用操作系统底层资源执行相应任务。

usafe.getAndAddInt

技术图片

底层汇编

技术图片

CAS小结

比较当前工作内存中的值和主内存中的值,如果相同则执行规定操作,否则继续比较直到主内存和工作内存的值一致为止。

CAS底层原理

Unsafe类+CAS思想(自旋)

CAS应用
CAS有三个操作数,内存值V,旧的预期值A,要修改的更新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

 CAS缺点

1.循环时间长,开销大

我们可以看到getAndAddInt方法执行时,有个do while。如果CAS比较失败,会一直进行尝试。如果CAS长时间一直不成功,可能会给CPU带来很大的开销。

技术图片

 2.只能保证一个共享变量的原子操作

当对一个共享变量执行操作时,我们可以使用循环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候就可以用锁来保证原子性。

3.引出ABA问题???

 

以上是关于juc学习二(CAS底层原理)的主要内容,如果未能解决你的问题,请参考以下文章

Java——聊聊JUC中的CAS原理

Java——聊聊JUC中的CAS原理

JUC多线程:Atomic原子类与CAS原理

Juc14_CAS的概述Unsafe类的原理CAS缺点ABA问题如何解决

cas底层原理

CAS原理解析 CAS底层