CAS原理(源码例子解析)

 通过Unsafe保证原子性

  • Unsafe  是CAS的核心类,由于Java方法无法直接访问底层系统,需要通过本地(native)方法来访问,基于该类可以直接操作特定内存的数据。(注意Unsafe类中的所有方法都是native修饰的,也就是说Unsafe类中的方法都直接调用操作系统底层资源执行相应任务)
  • 变量valueOffset,表示该变量在内存中的偏移地址,因为Unsafe就是根据内存偏移地址获取数据的。
  • 变量value用volatile修饰,保证了多线程之间的内存可见性。
     

CAS是一种系统原语,原语属于操作系统用语范畴,是由若干指令组成的,用语完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致性问题。 

 AtomicInteger 的 getAndIncrement 方法,相当于i++

CAS原理(源码例子解析)_第1张图片

 

CAS原理(源码例子解析)_第2张图片

假设线程A和线程B两个线程同时执行getAndAddInt操作(分别在不同CPU上)

1、 AtomicInteger里面的value原始值为3,即主内存中AtomicInteger的value为3,根据JMM模型,线程A和线程B各自持有一份值为3的value的副本分别到各自的工作内存。

2、线程A通过getIntVolatile(var1,var2)拿到value值3,这是线程A被挂起。

3、线程B也通过getIntVolatile(var1,var2)方法获得value值3,此时刚好线程B没有被挂起并执行compareAndSwap方法比较内存值也为3,成功修改内存值为4,线程B打完收工,一切OK。

4、这是线程A回复,执行compareAndSwapInt方法比较,发现手里的值3与内存值4不一致,说明该值已经被其他线程抢险异步修改过了,那A线程本次修改失败,只能重新读取重新来一遍了。

5、线程A重新获取value值,因为变量value被volatile修饰,所以其他线程对它的修改,线程A总是能够看到,线程A继续执行compareAndSwapInt进行比较替换,知道成功。

 

你可能感兴趣的:(JUC)