CAS算法与ABA问题

CAS算法与ABA问题锁是用来做并发最简单的方式 当然代价也是最高的 独占锁是一种悲观锁 synchronized 就是一种独占锁 它假设最坏的情况 并且只有在确保其它线程不会造成干扰的情况下执行 会导致其它所有需要锁的线程挂起直到持有锁的线程释放锁 所谓乐观锁就是每次不加锁 假设没有冲突而去完成某项操作 如果发生冲突了那就去重试 直到成功为止 CAS CompareAndSw 是一种有名的无锁算法

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

独占锁是一种悲观锁,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)方法,进行简单说明
该方法是这样的:

CAS算法与ABA问题

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

CAS算法与ABA问题

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

CAS算法与ABA问题

 

CAS(Compare And Swap)原理简述:

CAS算法与ABA问题

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

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

 

ABA问题:

CAS算法与ABA问题

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

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

 

解决ABA问题:

CAS算法与ABA问题

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

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

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

CAS算法与ABA问题

      画黄线的英文的意思为:AtomicMarkableReference

、可以给一个引用标记上一个标记位,来保证原子性。AtomicStampedReference

可以给一个引用标记上一个整型的版本戳,来保证原子性。

注:个人感觉AtomicStampedReference

使用相对较多,下面也只简单介绍AtomicStampedReference



给出AtomicStampedReference

部分API:

CAS算法与ABA问题

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

 

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

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

CAS算法与ABA问题

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

CAS算法与ABA问题

 

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

CAS算法与ABA问题

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

CAS算法与ABA问题

 

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

CAS算法与ABA问题

 

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

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

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

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

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

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

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

(0)
上一篇 2026年3月17日 上午11:26
下一篇 2026年3月17日 上午11:26


相关推荐

发表回复

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

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