Java开发中的乐观锁

390 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第30天,点击查看活动详情

Java开发中的乐观锁

介绍

悲观锁: 在修改数据时,总是认为别人会去修改同一条数据,所以每次操作时,都加上锁。

乐观锁: 在修改数据时,总是认为别人不会去修改同一条数据,所以每次修改时,不加锁,通过判断数据中的某一状态字段,来进行下面的操作。

CAS

乐观锁常见的实现方式是CAS和版本号,CAS,compare and swap,简单的讲就是在更新数据之前,判断一下数据是否被修改过,如果被修改过,则重试,如果没有被修改过,则直接更新。CAS包含了3个操作数

  1. 需要读写的内存位置V
  2. 进行比较的预期值A
  3. 拟写入的新值B

首先会判断内存位置V的值是否等于预期值A,如果等于,则将位置更新为新值B,如果不等于,则停止操作,但是很多CAS有有自旋操作,会一直重试。

CAS是由CPU支持的原子操作,其原子性是在硬件层面保证的。

版本号

第二种乐观锁实现方式是通过版本号,一般我们会在数据表中增加一个version字段,每次更新都带上version字段作为条件,并且在更新成功之后,将version字段+1并更新到数据库中,如果更新数据时的version条件和数据库中的不一致,则更新失败。

MybatisPlus乐观锁

  1. 首先我们需要配置乐观锁插件,这里演示一下Springboot注解方式
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}
  1. 我们需要在数据库实体类上增加version字段,并且还需要加上MybatisPlus的@version注解
@Version
private Integer version;
  1. 此时我们调用mybatisplus的updateById,乐观锁即会生效,注意,mybatisplus目前乐观锁插件仅支持updateById和update方法,并且更新的时候version字段需要有值,否则乐观锁不会生效的。