浅谈CAS原理_cas算法原理

浅谈CAS原理_cas算法原理1.背景我们知道,synchronized就是一种独占锁,独占锁是一个悲观锁,会导致其他所有需要锁的线程挂起,等待持有锁的线程释放锁。而另一种更加有效的锁就是乐观锁,CAS就是一种乐观锁2.CAS原理CAS(CompareAndSwap),比较并交换。我们知道,如果我要对一个变量进行操作,可以分为三个步骤读取该变量的值进行一系列的运算得到新的结果将运算的结果保存这儿需要知道CAS中有三个概念:内存地址的值V,旧值(从内存地址读取到的值)A,新值(进行操作后的结果值)。对应上面三

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

1. 背景

我们知道,synchronized就是一种独占锁,独占锁是一个悲观锁,会导致其他所有需要锁的线程挂起,等待持有锁的线程释放锁。而另一种更加有效的锁就是乐观锁,CAS就是一种乐观锁

2. CAS原理

CAS(Compare And Swap),比较并交换。我们知道,如果我要对一个变量进行操作,可以分为三个步骤

  1. 读取该变量的值
  2. 进行一系列的运算得到新的结果
  3. 将运算的结果保存

这儿需要知道CAS中有三个概念:内存地址的值V,旧值(从内存地址读取到的值)A,新值(进行操作后的结果值)B。对应上面三个步骤就是:值V保存在内存中,要修改的时候,会先去读取该内存中的值,读取到的值为A,此时A=V,然后进行操作得到结果B,此时需要将B写入内存才算是对该变量进行了完整的修改。那么此时需要再去读取内存中的值,判断该值是否等于A,如果等于,那么就直接将B写入。如果不等于,说明你在运算的过程中,其他的线程对该变量已经做了修改,那么你此时得到的这个B是没有意义的。不能写入。只能再次重复上面的操作(自旋),重新读取内存中的值,计算之后再进行比较,直到B可以被保存为止。这就是CAS的原理。

3. ABA问题

但是这种方式会有一个问题:ABA,就是说你在要保存B的时候,会去读取内存中的值判断是否和A相等,确保这期间没有其他线程操作过该变量。但是如果相等的话,你能确认这期间这个值没有被修改过吗?有可能期间被多次修改了,只不过最后得到的值恰好和原来的A相等。所以你不能保证相等时就是没有被修改过。这种情况可以加一个版本号来判断。例如1A-2B-3A,这样你就知道这个A其实已经不是原来的那个A了。

4. 缺点

因为该机制是没有加锁的,所有线程都可以任意操作该变量,虽然可以确保线程安全,但是如果并发太大,导致很多线程都在操作该变量,这会导致有大量的线程进行自旋,这无疑是增加了CPU的资源消耗。

5. 疑问

其实我自己有个疑问,这个真的安全吗?在保存B之前会判断内存中的值是否和A相等,相等就可以保存B。那如果有多个线程在操作该变量,操作完之后去读取内存中的值,并和各自线程中的A进行比较,假设这些线程都是在其他线程写入之前读取到内存中的值,也就是这几个线程读取到的值都和A相等,那么在写入的时候不就会出现先写入B值的线程的值会被后面写入的覆盖掉吗?

这个可能是自己对操作系统底层的原理不太了解,所以会有这样的疑问吧。

希望会这个问题的大佬不吝赐教,也希望自己以后在搞懂这个问题之后,来这儿将这个问题解决掉。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/184106.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • linux中lamp架构搭建_docker搭建redis集群

    linux中lamp架构搭建_docker搭建redis集群文章目录一、什么是LAMP架构二、各组件的作用1.Apache(前台)2.MYSQL(后台)3.PHP/Perl/Python4.linux三、LAMP架构安装一、什么是LAMP架构LAMP架构是目前成熟的企业网站应用模式之一,指的是协同工作的一整套系统和相关软件,能够提供动态Web站点服务及其应用开发环境。LAMP是一个缩写词,具体包括Linux操作系统、Apache网站服务器、MYSQL数据库服务器、PHP(Perl、python)网页编程语言。在构建LAMP架构时,各组件的安装顺序以此为Lin

    2022年10月16日
    2
  • 认识和使用COleVariant

    认识和使用COleVariant有时候会用到COleVariant类型数据.比如在CDaoRecordset::SetFieldValue()和GetFieldValue()中. 

    2022年7月18日
    13
  • linux 新建文件的命令

    图形界面下就不用说了,终端下键入:touchtest.java就创建了一个新文件test.javahttp://hovertree.com/menu/linux/http://www.cnbl

    2021年12月24日
    45
  • MYSQL经常使用命令列表

    MYSQL经常使用命令列表

    2021年12月16日
    36
  • yum 安装nginx_yum安装nginx

    yum 安装nginx_yum安装nginx前言:日常外出工作系统都是最小化安装,导致很多包都无法下载,需要自己手动安装包yum源以centos7.5为例在官网下载CentOS-7-x86_64-Everything-1804.iso上传到对应的服务器将镜像源挂载到对应的目录mount-oloop/opt/CentOS-7-x86_64-Everything-1804.iso/opt/yumrepo/tips:目录可以自定义修改路径/etc/yum.repos.dvirhel79.repo[rhel79]na

    2022年8月12日
    4
  • Java IO流知识点总结

    Java IO流知识点总结本主要对java的IO流知识点做比较全面的总结,但是没有很深入阐述。

    2022年5月20日
    42

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号