浅谈CAS原理_cas算法原理
1. 背景
我们知道,synchronized就是一种独占锁,独占锁是一个悲观锁,会导致其他所有需要锁的线程挂起,等待持有锁的线程释放锁。而另一种更加有效的锁就是乐观锁,CAS就是一种乐观锁
2. CAS原理
CAS(Compare And Swap),比较并交换。我们知道,如果我要对一个变量进行操作,可以分为三个步骤
- 读取该变量的值
- 进行一系列的运算得到新的结果
- 将运算的结果保存
这儿需要知道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.cn/184106.html原文链接:https://javaforall.cn
相关文章
- 算法与数据结构在我眼中的样子(1)排序算法
- nsga2 matlab,NSGA2算法特征选择MATLAB实现(多目标)
- 协同过滤推荐算法(一)原理与实现
- 决策树算法的原理(接地气版)
- 当面试官问我vue的 diff算法时,我会理直气壮地这么说
- 《算法竞赛进阶指南》0x23 剪枝
- nginx支持的负载均衡算法_nginx算法
- 7个步骤详解AdaBoost 算法原理和构建流程
- c语言最大公约数怎么求算法_最小公倍数c语言算法
- 彻底搞懂KMP算法原理
- 轻量型目标检测算法一次看个够
- 安全帽识别算法技术原理
- 【视频】Copula算法原理和R语言股市收益率相依性可视化分析|附代码数据
- 路由器原理及常用的路由协议、路由算法
- 【算法】双指针算法 ( 有效回文串 II )
- Redis常见限流算法原理及实现
- 非阻塞算法简介详解程序员
- 算法-第一个只出现一次的字符位置详解编程语言
- 算法-机器人的运动范围详解编程语言
- php生成数组的使用示例php全组合算法
- 使用python实现递归版汉诺塔示例(汉诺塔递归算法)