乐观锁
在面试过程中,我们经常会被问道乐观锁,悲观锁!这个其实非常简单!
乐观锁 : 故名思意十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题,
再次更新值测试
悲观锁:故名思意十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!
我们这里主要讲解 乐观锁机制!
乐观锁实现方式:
- 取出记录时,获取当前 version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
乐观锁:1、先查询,获得版本号 version = 1
-- A
update user set name = "itheibai",version = version + 1
where id = 2 and version = 1
-- B 线程抢先完成,这个时候 version = 2,会导致 A 修改失败!
update user set name = "itheibai",version = version + 1
where id = 2 and version = 1
测试一下MP的乐观锁插件
1、给数据库中增加version字段!

2、我们实体类加对应的字段
@Version // 乐观锁Version注解
private Integer version;
3、注册组件
package com.itheibai.config;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
// 扫描我们的 mapper 文件夹
@MapperScan("com.itheibai.mapper")
@EnableTransactionManagement
@Configuration // 配置类
public class MyBatisPlusConfig {
// 注册乐观锁插件
@Bean
public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
return new OptimisticLockerInnerInterceptor();
}
}
新版插件注册
// 扫描我们的 mapper 文件夹
@MapperScan("com.itheibai.mapper")
@EnableTransactionManagement
@Configuration // 配置类
public class MyBatisPlusConfig {
// 注册乐观锁插件
@Bean
public MybatisPlusInterceptor optimisticLockerInnerInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
4、测试一下!
// 测试乐观锁成功!
@Test
public void testOptimisticLocker() {
// 1.查询用户信息
User user = userMapper.selectById(1L);
// 2.修改用户信息
user.setName("itheibai");
user.setEmail("123456789@qq.com");
// 3.执行更新操作
userMapper.updateById(user);
}
// 测试乐观锁失败!多线程的情况下
@Test
public void testOptimisticLocker2() {
// 线程 1
User user = userMapper.selectById(1L);
user.setName("itheibai01");
user.setEmail("123456789@qq.com");
// 模拟另外一个线程执行了插队操作
User user1 = userMapper.selectById(1L);
user1.setName("itheibai02");
user1.setEmail("123456789@qq.com");
userMapper.updateById(user1);
// 自旋锁来多次尝试提交!
userMapper.updateById(user); // 如果没有乐观锁,就会覆盖插队线程的值!
}

评论前必须登录!
注册