锁是用来做并发最简单的方式,当然代价也是最高的。

独占锁是一种悲观锁,synchronized就是一种独占锁;它假设最坏的情况,并且只有在确保其它线程不会造成干扰的情况下执行,会导致其它所有需要锁的线程挂起直到持有锁的线程释放锁。

所谓乐观锁就是每次不加锁,假设没有冲突而去完成某项操作;如果发生冲突了那就去重试,直到成功为止。

CAS(Compare And Swap)是一种有名的无锁算法。CAS算法是乐观锁的一种实现。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B并返回true,否则返回false。

注:synchronized和ReentrantLock都是悲观锁。

注:什么时候使用悲观锁效率更高、什么使用使用乐观锁效率更高,要根据实际情况来判断选择。

提示:atomic中包下的类,采用的即为CAS乐观算法。

以AtomicInteger的public final int getAndSet(int newValue)方法,进行简单说明
该方法是这样的:

其调用了Unsafe类的public final int getAndSetInt(Object var1, long var2, int var4)方法:

而该方法又do{…}while(…)循环调用了本地方法public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

注:至于Windows/Linux下public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5)本地
     方法是如何实现的,推荐阅读https://blog.csdn.net/v123411739/article/details/79561458

CAS(Compare And Swap)原理简述:

       某一线程执行一个CAS逻辑(如上图线程A),如果中途有其他线程修改了共享变量的值(如:上图中线程A执行到笑脸那一刻时),导致这个线程的CAS逻辑运算后得到的值与期望结果不一致,那么这个线程会再次执行CAS逻辑(这里是一个do while循环),直到成功为止。

注:可能上图中某些地方写得并不规范,主要理解意思即可,不要在意细节。

ABA问题:

       如图所示,线程A进行CAS逻辑,在从内存中获取到var值到开始进行逻辑之间(对应图中笑脸处),会有一个时间差;如果刚好在这个时间差内,有其他某线程对var做了一系列的操作,但最后又恢复了var的值,即:出现“偷梁换柱”的情况;虽然此时线程A仍然能CAS成功,但是中间多出的那些过程仍然可能引发问题。

注:可能上图中某些地方写得并不规范,主要理解意思即可,不要在意细节。

注:上图A变为B再变回A,A的属性被修改了,如果程序此时刚好需要用上A的属性,那么就可能造成实际结果与理想结果不
     一致的情况。

注:根据实际情况,判断是否处理ABA问题。如果ABA问题并不会影响我们的业务结果,可以选择性处理或不处理;如果
     ABA会影响我们的业务结果的,这时就必须处理ABA问题了。
     追注:对于AtomicInteger等,没有什么可修改的属性;且我们只在意其结果值,所以对于这些类来说,本身就算发生了
              ABA现象,也不会对原线程的结果造成什么影响。

解决ABA问题:

我们可以通过加一个标识来解决这个问题;即:所有要用到某一共享引用的线程,如果在用到该引用时,都对该引用对应的标识进行推进的话,那么CAS在进行“上图中笑脸前笑脸后”对比时,除了要对比原来的引用(上图中的A)外,还要对比标识的值是否一样,这样就解决了ABA问题。

注:可能上图中某些地方写得并不规范,主要理解意思即可,不要在意细节。

注:这个标识只有一个职责,那就是计数,我们并不拿其值做什么业务有关的操作。

注:各种乐观锁的实现中通常都会用版本戳version来标记对象,进而避免ABA问题。在Java中,
     AtomicMarkableReference<V>、AtomicStampedReference<V>也实现了这个作用。

画黄线的英文的意思为:AtomicMarkableReference<V>、可以给一个引用标记上一个标记位,来保证原子性。AtomicStampedReference<V>可以给一个引用标记上一个整型的版本戳,来保证原子性。

注:个人感觉AtomicStampedReference<V>使用相对较多,下面也只简单介绍AtomicStampedReference<V>。

给出AtomicStampedReference<V>部分API:

注:更多细节详见API手册。

声明:下列示例均为笔者按照自己的理解敲的示例,如有不当之处,欢迎指正!

代码简单示例ABA问题的发生:

运行主函数,控制台输出结果为:

代码简单示例解决ABA问题的思路:

运行主函数,控制台输出结果为:

笔者将本人多线程一栏中博客涉及到的所有代码示例(Lock分开放在一个专门的项目、synchronized的代码附在该文章末尾),放在GIT上了(链接见本文末),这里先给出一个所涉及内容图:

^_^ 如有不当之处,欢迎指正

^_^ 参考视频
           《Java多线程与并发实战视频课程》,齐毅

^_^ 参考链接
              https://www.cnblogs.com/onlywujun/articles/3529572.html
              https://www.cnblogs.com/549294286/p/3766717.html
              https://blog.csdn.net/v123411739/article/details/79561458
              https://www.cnblogs.com/exceptioneye/p/5373498.html

^_^ 多线程一栏所有测试示例代码,托管链接
              https://github.com/JustryDeng/PublicRepository

^_^ 本文已经被收录进《程序员成长笔记(三)》,笔者JustryDeng

CAS算法与ABA问题相关推荐

  1. 并发策略-CAS算法

    对于并发控制而言,我们平时用的锁(synchronized,Lock)是一种悲观的策略.它总是假设每一次临界区操作会产生冲突,因此,必须对每次操作都小心翼翼.如果多个线程同时访问临界区资源,就宁可牺牲 ...

  2. CAS算法-实现原理

    目录 CAS是什么? CAS解决了什么问题? CAS存在什么问题? CAS有哪些应用场景? cas的实现 最后 CAS是什么? CAS的全称为Compare and swap 比较并交换.CAS又经常 ...

  3. 面试:CAS算法原理

    1.什么是CAS? CAS:Compare and Swap,即比较再交换. jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronou ...

  4. JAVA中的CAS算法

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

  5. 真实业务场景展现CAS原理的ABA问题及解决方案

    文章目录 阅读提示 CAS原理.ABA问题介绍 真实业务场景 如何解决ABA问题 CAS学习总结 阅读提示 本文将借助开保险柜的业务场景重点阐述误用AtomicBoolean引起的ABA问题,以及解决 ...

  6. CAS算法AtomicInteger

    https://www.jianshu.com/p/cec71079acdf (相当完整) 题一:java中的CAS是什么? 问题二:为什么要使用CAS? 问题三:CAS使用中需要注意什么问题? 这里 ...

  7. CAS算法的理解及应用

    应用 原子操作类,例如AtomicInteger,AtomicBoolean - 适用于并发量较小,多cpu情况下: Java中有许多线程安全类,比如线程安全的集合类.从Java5开始,在java.u ...

  8. java cas 实现_Java CAS算法简介及简单模拟CAS算法

    CAS(Compare-And-Swap:比较并替换) CAS是英文单词CompareAndSwap的缩写,意思就是:比较并替换.简单来说就是比较之后再看情况是否需要替换.CAS是乐观锁思想的一种实现 ...

  9. (转)利用CAS算法实现通用线程安全状态机

    在多线程环境下,如果某个类是有状态的,那我们在使用前,需要保证所有该类的实例对象状态一致,否则会出现意向不到的bug.下面是通用线程安全状态机的实现方法. public class ThreadSav ...

最新文章

  1. 用pandas.dataframe 的append()方法时候,合成的整个数据的索引是分块的
  2. HTML-JS 循环 函数 递归
  3. 什么是实验室人员比对人员_CNAS实验室认可对人员、设备的要求
  4. 多路平衡查找树 --- B(B-)树
  5. .Net Core 开发成长路线图
  6. 基于WebRTC开源框架的实时视频聊天项目,搭建私人实时通信服务
  7. CAD快捷键命令大全
  8. Unmapped Spring configuration files found.
  9. 看英语数据手册很难?5步帮你搞定!
  10. html 鼠标划过 ie导致白屏,win7系统IE浏览器网页出现白屏的解决方法
  11. [高通SDM450][Android9.0]CTA认证--拆分申请权限分组
  12. Cisco WSA配置
  13. 邀你来看 | CSDN公开课 利用容器技术打造AI公司技术中台
  14. vtd和vt的区别_vi和vt的区别小窍门
  15. ubuntu新建账户并赋予root权限
  16. 學習雜記(SpringCloud)
  17. 在CODESYS中通过EtherCAT总线驱动单个电机
  18. java 不定参数_JAVA不定参数探秘
  19. 关于新电脑快速安装开发环境
  20. 《OpenCV3编程入门-毛星云》第三部分 掌握imgproc组件

热门文章

  1. 如何解决App inventor和AI伴侣无法连接的问题
  2. 微信小程序onPullDownRefresh onReachBottom实现下拉刷新上拉分页加载
  3. windows中如何给程序添加管理权限和添加数据保护(dep)
  4. Java8 提供CompletableFuture来简化高并发异步处理编程
  5. Excel无法vlookup事件
  6. Java 和 MySQL 数据类型对照表
  7. 显卡,显卡驱动,nvcc, cuda driver,cudatoolkit,cudnn
  8. 计算机保存不了自动还原,win7系统颜色校准无法保存开机自动还原默认的处理步骤...
  9. android网购功能,网购Android App购物车点击动画实现详解
  10. 新一配:iPod及其配置介绍【转载】