在面试过程中,乐观锁、悲观锁经常被提问

    乐观锁: 顾名思义十分乐观,它总是认为不会出现问题,无论干什么都不去上锁,如果出现了问题,再次更新值测试

    悲观锁:顾名思义十分悲观,他总是认为会出现问题,无论干什么都会上锁,再去操作

    乐观锁实现方式:

    • 取出记录时,获取当前 version
    • 更新时,带上这个 version
    • 执行更新时, set version = newVersion where version = oldVersion
    • 如果 version 不对,就更新失败
    1. 乐观锁:1、先查询,获得版本号 version = 1
    2. -- A
    3. update user set name = "cedric",version = version + 1
    4. where id = 2 and version = 1
    5. -- B 线程抢先完成,这个时候 version = 2,会导致 A 修改失败
    6. update user set name = 'cedric',version = version + 1
    7. where id = 2 and version = 1

    测试MyBatisPlus的乐观锁插件

    1、给数据库中增加version字段
    image.png

    2、实体类增加对应的字段

    1. @Version //乐观锁Version注解
    2. private Integer version;

    3、注册组件

    1. // 扫描Mapper文件夹
    2. @MapperScan("com.cedric.mybatisplus.mapper")
    3. @EnableTransactionManagement
    4. @Configuration
    5. public class MyBatisPlusConfig {
    6. // 注册乐观锁插件
    7. @Bean
    8. public OptimisticLockerInterceptor optimisticLockerInterceptor() {
    9. return new OptimisticLockerInterceptor();
    10. }
    11. }

    4、测试一下

    1. // 测试乐观锁成功
    2. @Test
    3. public void testOptimisticLocker(){
    4. // 1.查询用户信息
    5. User user = userMapper.selectById(1L);
    6. // 2.修改用户信息
    7. user.setName("张三");
    8. user.setEmail("zhangsan@sina.cn");
    9. // 3.执行更新操作
    10. userMapper.updateById(user);
    11. }
    12. // 测试乐观锁失败(多线程下)
    13. @Test
    14. public void testOptimisticLocker2(){
    15. // 线程1
    16. User user = userMapper.selectById(1L);
    17. user.setName("张三11111");
    18. user.setEmail("zhangsan@sina.cn");
    19. // 模拟另一个线程执行了插队操作
    20. User user2 = userMapper.selectById(1L);
    21. user2.setName("张三2222");
    22. user2.setEmail("zhangsan@qq.com");
    23. userMapper.updateById(user2);
    24. userMapper.updateById(user); //如果没有乐观锁就会覆盖插队线程的值
    25. }

    image.png