上篇文章通过自旋锁保证了数据的准确性,现在我们讨论一个问题。
【PS:看这个问题前需要确保已经明白自旋锁的执行原理】
业务:获取对象名称,根据名称对数据进行相关处理。
如图:
【上图我们发现并发时使用CAS处理业务可能会因多条线程同时操作导致某些业务被重复操作,出现ABA问题】
QA:如何解决CAS的ABA问题?
思路:使用版本号控制(例:mysql的乐观锁)
定义一个字段用于存放版本号version,获取name的时候同时获取version,每个线程成功操作都给version执行+1操作。
基于上图:
获取信息:
threadA:version = 1,name=A
threadC:version = 1,name=A
threadA操作:
校验:
version是否等于1,name是否等于A
满足条件:
设置version=2,name等于B
threadB:
获取信息:
version = 2,name=B
校验:
version是否等于2,name是否等于B
满足条件:
设置version=3,name等于A
threadC操作:
校验:
version是否等于1,name是否等于A
不满足:
name等于A但是version=3 ==》被其他线程操作过
获取对象最新的version与name继续进行业务预处理
校验:
当前获取的version、name与对象中持有的是否一致
一致:
将业务处理结果赋值给对象
不一致:
继续获取对象当前version、name对业务做预处理然后校验原始信息是否一致(此时进入一个循环状态【自旋的概念因此而来】,直到能够给对象赋值为止)
满足条件:
将业务处理结果赋值给对象