问题一:java中的CAS是什么?

问题二:为什么要使用CAS?

问题三:CAS使用中需要注意什么问题?

这里以提问的方式引出话题,下面带大家慢慢了解CAS。

1.CAS的含义

CAS是compare and swap的缩写,即我们所说的比较交换。cas是一种基于锁的操作,而且是乐观锁。在java中锁分为乐观锁和悲观锁。悲观锁是将资源锁住,等一个之前获得锁的线程释放锁之后,下一个线程才可以访问。而乐观锁采取了一种宽泛的态度,通过某种方式不加锁来处理资源,比如通过给记录加version来获取数据,性能较悲观锁有很大的提高。

CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存地址里面的值和A的值是一样的,那么就将内存里面的值更新成B。CAS是通过无限循环来获取数据的,若果在第一轮循环中,a线程获取地址里面的值被b线程修改了,那么a线程需要自旋,到下次循环才有可能机会执行。

2.CAS的问题

①.CAS容易造成ABA问题。一个线程a将数值改成了b,接着又改成了a,此时CAS认为是没有变化,其实是已经变化过了,而这个问题的解决方案可以使用版本号标识,每操作一次version加1。在java5中,已经提供了AtomicStampedReference来解决问题。

②.CAS造成CPU利用率增加。之前说过了CAS里面是一个循环判断的过程,如果线程一直没有获取到状态,cpu资源会一直被占用。

3.看AutoInteger的实现源码

其实AutoInteger就是使用了CAS来实现加1,我们知道如果有一个共享变量count=1,开5个线程,每个线程加20次,结果一般来说都会小于100.

@Test
public void test20() throws InterruptedException {for (int i = 1; i <= 5; i++) {MyThrend thrend = new MyThrend("thead" + i);
        Thread thread = new Thread(thrend);
        thread.start();
    }Thread.sleep(2000);
    System.out.println(MyCount1.count);
}static class MyThrend implements Runnable {private String name;
    MyThrend(String threadName) {this.name = threadName;
    }@Override
    public void run() {for (int i=0;i<20;i++)MyCount1.count++;
    }
}private static class MyCount1 {static int count = 0;
}

结果78

现在修改一个代码,将int变成AtomicInteger

@Test
public void test20() throws InterruptedException {for (int i = 1; i <= 5; i++) {MyThrend thrend = new MyThrend("thead" + i);
        Thread thread = new Thread(thrend);
        thread.start();
    }Thread.sleep(2000);
    System.out.println(MyCount.count.get());
}static class MyThrend implements Runnable {private String name;
    MyThrend(String threadName) {this.name = threadName;
    }@Override
    public void run() {for (int i=0;i<20;i++)MyCount.count.getAndIncrement();  //加1方法
    }
}private static class MyCount {static AtomicInteger count = new AtomicInteger(0);
}

每次结果都是100,怎么做到的呢?这里是没有直接加锁的,看源码。

public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);  //第一个参数当前对象地址,第二个参数数据偏移量,第三个参数每次指定默认加1
}
public final int getAndAddInt(Object var1, long var2, int var4) {  //这个方法使用的就是CAS,核心在于循环比较内存里面的值和当前值是否相等,如果相等就用新值覆盖int var5;
    do {var5 = this.getIntVolatile(var1, var2);  //如果a,b线程同时执行这个方法,a线程拿到值1后cpu执行时间到了挂起,b开始执行,也拿到1,但是没有挂起,接着将值变成了2
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));  //这个时候a线程恢复执行,去比较的时候发现手上的1 和内存里面的值2不等,这个时候他要进行下一个循环,看出来了占用cpu吧
    return var5;
}

AtomicInteger,AtomicLong,AtomicBoolean.....都在java.util.current.atomic包下面,采用了CAS机制来实现加锁,里面具体方法就不看了,留给大家后续研究!

什么是java中的CAS相关推荐

  1. 【面试篇】Java多线程并发-Java中的CAS机制算法

    Java中的CAS机制算法 a.CAS例子 再讲解CAS机制之前,先来看一道经典的并发执行1000次递增的问题: public class Test { public static int count ...

  2. 【高并发】java中的CAS,你需要知道的东西

    1.概述 转载:添加链接描述 从网站计数器实现中一步步引出CAS操作 介绍java中的CAS及CAS可能存在的问题 悲观锁和乐观锁的一些介绍及数据库乐观锁的一个常见示例 使用java中的原子操作实现网 ...

  3. JAVA 中的 CAS

    原文地址:https://www.xilidou.com/2018/02/01/java-cas/ CAS 是现代操作系统,解决并发问题的一个重要手段,最近在看 eureka 的源码的时候.遇到了很多 ...

  4. Java中的CAS操作

    Java中的CAS的含义 CAS即是Compare and Swap ,它是JDK提供的非阻塞原子性操作,它通过硬件保证了比较一更新操作的原子性.CAS 操作包含三个操作数-内存位置(V).预期原值( ...

  5. Java中的CAS以及AQS实现原理

    Java中的CAS实现原理 什么是CAS? 在计算机科学中,比较和交换(Conmpare And Swap)是用于实现多线程同步的原子指令. 它将内存位置的内容与给定值进行比较,只有在相同的情况下,将 ...

  6. java中的CAS和原子类的实现

    什么是CAS     CAS的全称为Compare-And-Swap,直译就是对比交换.是一条CPU的原子指令,其作用是让CPU先进行比较两个值是否相等,然后原子地更新某个位置的值,经过调查发现,其实 ...

  7. JAVA中的CAS算法

    java 中的线程之间的栈空间是相互独立,堆空间是共享的 V:内存值就是主内存中i值 A:预估值(期望值)就是子线程拿到主内存的值(读取到高速缓存中的值) B:更新值是子线程拿到i值后,修改i的值 假 ...

  8. 猫头鹰的深夜翻译:Java中的CAS(Compare And Swap)

    题目要求 在我们深入了解CAS(Compare And Swap)策略以及它是如何在AtomicInteger这样的原子构造器中使用的,首先来看一下这段代码: public class MyApp { ...

  9. Java中的CAS(compare and swap)

    定义: 拿着寄存器/某个内存 中的值和另外一个内存的值进行比较,如果值相同了,就把两者交换 boolean CAS(address, expectValue, swapValue){if(&a ...

最新文章

  1. (树)判断二叉树是否为BST
  2. c# timer使用
  3. 【2012百度之星/资格赛】F:百科蝌蚪团
  4. Java之对List里面的对象名字进行模糊查询
  5. php 静态方法 call,php的 __callStatic 函数
  6. thinkphp如何部署到宝塔面板nginx服务器
  7. linux unshare 命令,详解Linux Namespace之User
  8. 大屏数据可视化综合设计
  9. 如何自己用U盘重装系统
  10. springMvc将对象json返回时自动忽略掉对象中的特定属性的注解方式
  11. LiveRTMP之MP4文件进行rtmp点播直播推送(三)
  12. NVisionXRFBXConverter(Beta版)实践课程
  13. 编曲时如何在FL Studio卷帘窗口修改单个音符音量
  14. 基于CentOS7配置ArcGIS enterprise
  15. Oracle导入导出之dmp
  16. 递归算法php,php递归算法经典实例
  17. FileZilla 使用技巧
  18. [ PyQt入门教程 ] Qt Designer工具的使用
  19. Android GIF图片显示
  20. java单链表反转(头插法)详解

热门文章

  1. vue【element ui】el-date-picker 日期选择器控件 限制可选的开始时间和结束时间
  2. 【python实战】多线程下载文件
  3. C++ 并行编程(thread)
  4. 数据解读 | 离开互联网大厂的年轻人都去了哪儿?
  5. 梦魇java_[Java教程]魔鬼的梦魇—验证IE中的JS内存泄露模式(一)
  6. 第一次写点东西,希望是个好的开始
  7. vue.js用benz-amr-recorder实现播放amr格式音频
  8. 微软在线文档库(docs.microsoft.com),MVP Challenge
  9. 上亿条个人信息被泄露 源头竟是房产商
  10. 027 大数据之Azkaban调度系统