CAS场景及解决ABA问题

导读:本篇文章讲解 CAS场景及解决ABA问题,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

CAS场景及例子

假如你往地上仍1万块钱,是不是一定会丢呢?这要看情况了,如果是在人来人往的都市,可以说肯定会丢的。如果你跑到无人区扔地上,可以说肯定不会丢。

可以看到,都是把东西无保护的放到公共区域里,结果却相差很大。这说明安全问题还和公共区域的环境状况有关系。

比如我把数据放到公共区域的堆内存中,但是始终都只会有1个线程,也就是单线程模型,那这数据肯定是安全的。

再者说,2个线程操作同一个数据和200个线程操作同一个数据,这个数据的安全概率是完全不一样的。肯定线程越多数据不安全的概率越大,线程越少数据不安全的概率越小。取个极限情况,那就是只有1个线程,那不安全概率就是0,也就是安全的。

可能你又猜到了我想表达的内容了,没错,就是CAS。可能大家觉得既然锁可以解决问题,那就用锁得了,为啥又冒出了个CAS呢?

那是因为锁的获取和释放是要花费一定代价的,如果在线程数目特别少的时候,可能根本就不会有别的线程来操作数据,此时你还要获取锁和释放锁,可以说是一种浪费。

针对这种“地广人稀”的情况,专门提出了一种方法,叫CAS(Compare And Swap)。就是在并发很小的情况下,数据被意外修改的概率很低,但是又存在这种可能性,此时就用CAS。

假如一个线程操作数据,干了一半活,累了,想要去休息。(貌似今天的线程体质都不太好)。于是它记录下当前数据的状态(就是数据的值),回家睡觉了。

醒来后打算继续接着干活,但是又担心数据可能被修改了,于是就把睡觉前保存的数据状态拿出来和现在的数据状态比较一下,如果一样,说明自己在睡觉期间,数据没有被人动过(当然也有可能是先被改成了其它,然后又改回来了,这就是ABA问题了),那就接着继续干。如果不一样,说明数据已经被修改了,那之前做的那些操作其实都白瞎了,就干脆放弃,从头再重新开始处理一遍。

所以CAS这种方式适用于并发量不高的情况,也就是数据被意外修改的可能性较小的情况。如果并发量很高的话,你的数据一定会被修改,每次都要放弃,然后从头再来,这样反而花费的代价更大了,还不如直接加锁呢。

ABA问题

这里再解释下ABA问题,假如你睡觉前数据是5,醒来后数据还是5,并不能肯定数据没有被修改过。可能数据先被修改成8然后又改回到5,只是你不知道罢了。对于这个问题,其实也很好解决,再加一个版本号字段就行了,并规定只要修改数据,必须使版本号加1。

这样你睡觉前数据是5版本号是0,醒来后数据是5版本号是0,表明数据没有被修改。如果数据是5版本号是2,表明数据被改动了2次,先改为其它,然后又改回到5。

我再次相信聪明的你已经发现了,这里的CAS其实就是乐观锁,上一种方案里的获取锁和释放锁其实就是悲观锁。乐观锁持乐观态度,就是假设我的数据不会被意外修改,如果修改了,就放弃,从头再来。悲观锁持悲观态度,就是假设我的数据一定会被意外修改,那干脆直接加锁得了。


这里特别感谢这篇文章的来源

—>https://www.cnblogs.com/lixinjie/p/a-answer-about-thread-safety-in-a-interview.html#top
博主写的非常好,我只是拿出来一部分觉得例子和讲解非常好,转载来和大家一起学习!!

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

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/85278.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!