JUC并发编程学习笔记(十八)深入理解CAS

笑看天下无敌手  金牌会员 | 2023-12-13 04:27:52 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 985|帖子 985|积分 2955

深入理解CAS

什么是CAS
为什么要学CAS:大厂你必须深入研究底层!有所突破!
java层面的cas------->compareAndSet
compareAndSet(int expectedValue, int newValue) 期望并更新,达到期望值就更新、否则就不更新!
  1. package org.example.cas;
  2. import java.util.concurrent.atomic.AtomicInteger;
  3. public class CASDemo {
  4.     public static void main(String[] args) {
  5.         AtomicInteger atomicInteger = new AtomicInteger(2020);
  6.         //JAVA CAS -> 比较并交换
  7.         //期望、更新
  8.         //compareAndSet(int expectedValue, int newValue)
  9.         //如果我期望的值达到了那么就跟新、否则就不更新;CAS 是CPU的并发原语!
  10.         System.out.println(atomicInteger.compareAndSet(2020, 2021));
  11.         //达到期望值更新成功
  12.         System.out.println(atomicInteger.get());
  13.         //更新后未达到期望值,更新失败
  14.         System.out.println(atomicInteger.compareAndSet(2020, 2021));
  15.         System.out.println(atomicInteger.get());
  16.     }
  17. }
复制代码
Unsafe类
java不能直接操作内存,但是可以调用c++,c++可以操作内存,java可以通过native关键字定义的方法来调用c++。Unsafe类就像是java留给自己的一个后门。所以Unsafe类中都是native方法和调用native方法的方法!
在原子类里,有一个getAndIncrement方法用作自增、那么他的底层是如何实现的呢?
其实就是调用的unsafe类中的getAndAddInt方法
  1. public final int getAndIncrement() {
  2.     //dalta传入了1
  3.     return U.getAndAddInt(this, VALUE, 1);
  4. }
复制代码
  1. public final int getAndAddInt(Object o, long offset, int delta) {
  2.     int v;
  3.     do {
  4.         //v每次都跟新为最新值,所以一直会是期望的值!就执行了++的操作
  5.         v = getIntVolatile(o, offset);
  6.         //如果当前对象o期望的值等于v,那么将当前对象o的值跟新为v+dalta;
  7.     } while (!weakCompareAndSetInt(o, offset, v, v + delta));
  8.     return v;
  9. }
复制代码
  1. public final boolean weakCompareAndSetInt(Object o, long offset,
  2.                                               int expected,
  3.                                               int x) {
  4.         return compareAndSetInt(o, offset, expected, x);
  5.     }
复制代码
  1. public final native boolean compareAndSetInt(Object o, long offset,
  2.                                                  int expected,
  3.                                                  int x);
复制代码
对比观察,其实getAndAddInt就是定义一个变量取到最新的值,然后通过while循环一直更新,其中getIntVolatile和compareAndSetInt都是通过java调用底层c++操作内存。
其中用到了一段标准的锁(自旋锁!):
  1. do {
  2.         //v每次都跟新为最新值,所以一直会是期望的值!就执行了++的操作
  3.         v = getIntVolatile(o, offset);
  4.         //如果当前对象o期望的值等于v,那么将当前对象o的值跟新为v+dalta;
  5.     } while (!weakCompareAndSetInt(o, offset, v, v + delta));
复制代码
缺点
1、循环会耗时
2、一次性只能保证一个共享变量的原子性
3、会存在ABA问题
优点
自带原子性
CAS        :        ABA问题(狸猫换太子)!
  1. package org.example.cas;
  2. import java.util.concurrent.atomic.AtomicInteger;
  3. public class CASDemo {
  4.     public static void main(String[] args) {
  5.         AtomicInteger atomicInteger = new AtomicInteger(2020);
  6.         //JAVA CAS -> 比较并交换
  7.         //期望、更新
  8.         //compareAndSet(int expectedValue, int newValue)
  9.         //如果我期望的值达到了那么就跟新、否则就不更新;   CAS 是CPU的并发原语!
  10.         //===============捣乱的线程================
  11.         System.out.println(atomicInteger.compareAndSet(2020, 2021));
  12.         System.out.println(atomicInteger.compareAndSet(2021, 2020));
  13.         //达到期望值更新成功
  14.         System.out.println(atomicInteger.get());
  15.         //更新后未达到期望值,更新失败
  16.         //===============期望的线程================
  17.         System.out.println(atomicInteger.compareAndSet(2020, 2021));
  18.         System.out.println(atomicInteger.get());
  19.         //getAndIncrement number++ 底层如何实现的?
  20.         atomicInteger.getAndIncrement();//++方法
  21.     }
  22. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

笑看天下无敌手

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表