• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

CAS乐观锁解决并发问题的一次实践

武飞扬头像
捡田螺的小男孩
帮助16

前言

最近做新项目,货币充值消耗,送礼竞争勋章等都使用了CAS解决并发问题,所以做一下笔记,谈谈CAS,大家一起互相学习。

乐观锁,悲观锁:

讨论CAS的话,先来说有一下乐观锁,悲观锁。

悲观锁:每次去取数据,很悲观,都觉得会被别人修改,所以在拿数据的时候都会上锁。简言之,共享资源每次都只给一个线程使用,其他线程阻塞,等第一个线程用完后再把资源转让给其他线程。synchronized和ReentranLock等都是悲观锁思想的体现。

乐观锁:每次去取数据,都很乐观,觉得不会被被人修改。因此每次都不上锁,但是在更新的时候,就会看别人有没有在这期间去更新这个数据,如果有更新就重新获取,再进行判断,一直循环,直到拿到没有被修改过的数据。CAS(Compare and Swap 比较并交换)就是乐观锁的一种实现方式。

CAS算法:

CAS涉及三个操作数

1.需要读写的内存地址V

2.进行比较的预期原值A

3.拟写入的新值B

如果内存位置的值V与预期原A值相匹配,那么处理器会自动将该位置值更新为新值B。CAS思想:要进行更新时,认为位置V上的值还是跟A值相等,如果是是相等,就认为它没有被别的线程更改过,即可更新为B值。否则,认为它已经被别的线程修改过,不更新为B的值,返回当前位置V最新的值。

JDK源码中,CAS思想体现:

反编译Unsafe类(用Java Decompiler工具)

从源码中可以发现,内部使用自旋的方式进行CAS更新

 

业务场景以及CAS的应用:

假设多人A,B,C等给D送礼,送总价值最多的那个人,可以成为佩带D的守护皇冠,D的守护皇冠有且只有一个。如果他们同时在给D送礼,送礼价值互相超越,即存在并发问题。

解决思路: 参考乐观锁原理

  • 设置乐观锁失败后尝试次数n次
  • 先查询旧的守护者,即旧的送礼最大价值者。
  • 如果当前旧的守护者不为空,构造当前送礼者为新守护者。
  • 将新的守护者去跟旧的守护者比较送礼的价值,尝试更新数据库。
  • 如果发现更新时,旧的最大送礼价值发生改变了,放弃更新,退出循环,重新尝试(n--)。
  • 如果当前旧的守护者为空,表示以前还没有守护,直接将新的守护插入表。
  • 如果插入表失败,表示在插入过程中,数据被更改了,表明有新的记录抢先成为守护。
  • 那么,重新尝试(n--),直到次数n用完。

抢占守护流程图:

 

代码实现:

 

 

CAS存在的一些问题:

1.ABA问题,

并发环境下,假设初始条件是A,去修改数据时,发现是A就会执行修改。但是看到的虽然是A,中间可能发生了A变B,B又变回A的情况。此时A已经非彼A,数据即使成功修改,也可能有问题。

2.CPU开销

自旋CAS,如果一直循环执行,一直不成功,会给CPU带来非常大的执行开销。所以上面抢占守护的例子,设置了尝试的执行次数n,避免一直循环

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanfbeia
系列文章
更多 icon
同类精品
更多 icon
继续加载