1:乐观锁
1.1:乐观锁简介
乐观锁:总是假设最好的情况,在读取数据的使用不会发生并发问题,但在更新的时候比较原数据是否被其他线程发生了改变。主要通过通过版本号机制或CAS算法实现,适用于读多写少的应用场景。
版本号机制:在数据库表中加一个版本号version字段,表示数据被修改的次数,在修改数据前先读取该表中的版本号字段,在修改的使用对比是否是自己读取出来的版本号如果是则进行更新操作并版本号(version)加1如果不是则重新执行进行更新操作直到更新成功为止。
CAS:compare and swap 顾名思义就是比较与替换。CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。
内存位置的值是否与预期原值一样如果一样则用新值更新,如果不则重试。CAS算法实现会导致ABA问题的产生。
ABA问题:A线程某一时刻获取内存位置的值为10,与其原值也为10,在这个过程中假设B线程对内存位置的值进行了修改,修改我为12,下一毫米又对内存中的值进行了修改,修改为10。这是A线程把值修改为13修改成功。这就是ABA问题。通俗易懂的来讲就是:你大爷是你大爷,你大妈已经不是你大妈了。乐观锁通常使用版本号机制来避免ABA问题。
1.2:乐观锁的例子
未使用乐观锁(实现存钱取钱)
A操作人员 | B操作人员 |
---|---|
查询余额(100¥) | 查询余额(100¥) |
存入10¥(100¥+10¥) | 喝咖啡中 |
喝咖啡中 | 取出10¥(100¥-10¥) |
查询余额 (90¥) | 喝咖啡中 |
查询余额 (90¥) | 查询余额 (90¥) |
以使用乐观锁(实现存钱取钱)
A操作人员 | B操作人员 |
---|---|
查询余额(100¥)version=1 | 查询余额(100¥)version=1 |
存入10¥(100¥+10¥)把查询余额中的version进行对比匹配version+1充值成功 | 喝咖啡中 |
喝咖啡中 | 取出10¥(100¥-10¥)把查询余额中的version进行对比,结果不匹配 ,取出不成功,重新进行取钱操作,查询余额(110¥)version=2,把查询余额中的version进行对比匹配version+1取出成功 (110¥-10¥) |
查询余额 (100¥) | 喝咖啡中 |
查询余额 (100¥) | 查询余额 (100¥) |
2:springboot整合mybatisPlus 乐观锁插件
本章会设计到 springboot整合mybatisPlus整合使用,springboot整合swagger2整合使用,需要的可以看我其他的博文
2.1 插件配置
package cloud.xingzhe.springbootmybatisplus;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@MapperScan