- 乐观锁 : 故名思意十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题,
再次更新值测试 - 悲观锁:故名思意十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!
乐观锁实现方式:
- 取出记录时,获取当前 version
- 更新时,带上这个version
- 执行更新时,
set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
乐观锁:
--A
1、先查询,获得版本号 version = 1 -- A update user set name = "wwj", version = version + 1 where id = 2 and version = 1
-- B 线程抢先完成,这个时候 version = 2,会导致 A 修改失败! update user set name = "wwj", version = version + 1 where id = 2 and version = 1
具体实现
1、给数据库中增加version字段!
2、我们实体类加对应的字段和注解
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@TableId(type = IdType.AUTO)
private long id;
private String name;
private Integer age;
private String email;
@TableField(fill = FieldFill.INSERT) //自动填充
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE) //自动填充
private Date updateTime;
@Version //乐观锁
private Integer version;
}
3、注册组件
增加config
模块,然后编写MyBatisPlusConfig.java
用于注册组件
@MapperScan("com.wwj.mapper")
@EnableTransactionManagement //事务管理
@Configuration //配置类
public class {
// 注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
}
4.测试一下
//测试乐观锁
@Test
public void testOptimisticLocker(){
User user = userMapper.selectById(1L); //
// 2、修改用户信息
user.setName("wwj333");
user.setEmail("24736743@qq.com");
// 3、执行更新操作
userMapper.updateById(user);
}
可见执行成功:数据更改且version更新
测试乐观锁的保护机制:模拟多线程修改数据
@Test
public void testOptimisticLocker2(){
//线程1
User user1 = userMapper.selectById(1L);
user1.setName("wwj1");
user1.setEmail("24736743111@qq.com");
//线程2
User user2 = userMapper.selectById(1L);
user2.setName("wwj2");
user2.setEmail("24736743222@qq.com");
userMapper.updateById(user2);
// 自旋锁来多次尝试提交!
userMapper.updateById(user1); // 如果没有乐观锁就会覆盖插队线程的值!
}
执行完成后,发现只执行了一次,后一次的修改并未成功;