什么叫乐观锁呢?百度百科上是这样说的:
乐观锁机制采取了更加宽松的加锁机制。相对悲观锁而言,乐观锁更倾向于开发运用。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。而乐观锁机制在一定程度上解决了这个问题。
看百度百科上的例子:
如一个金融系统,当某个操作员读取用户的数据,并在读出的用户数据的基础上进行修改时(如更改用户帐户余额),如果采用悲观锁机制,也就意味着整个操作过 程中(从操作员读出数据、开始修改直至提交修改结果的全过程,甚至还包括操作 员中途去煮咖啡的时间),数据库记录始终处于加锁状态,可以想见,如果面对几百上千个并发,这样的情况将导致怎样的后果。所以面对这种情况我们可以用乐观锁,它在一定程度上解决了这个问题,一般我们都使用数据版本(Version)记录机制实现,即向数据库表中添加version字段。
接下来我们来看看怎么用java来实现乐观锁:
一、假设我们有一张商品表,并添加了如下数据。
二、向表中添加verson字段。
三、修改实体类,添加@Version 注解。
@Data
public class Product {
private Long id;
private String name; //商品名称
private Integer price; //商品价格
@Version // 加了此注解所有的增删改都要带上版本字段
private Integer version;
}
四、注册乐观锁插件
springboot注册方式:
@EnableTransactionManagement
@Configuration
@MapperScan("com.atguigu.mybatis_plus.mapper")
public class MybatisPlusConfig {
/**
* 乐观锁插件
* @return
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
spring xml注册方式:
<bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>
五、测试
@SpringBootTest
public class LockTest {
@Autowired
private ProductMapper productMapper;
@Test
public void testLock() {
// 1、小李
Product p1 = productMapper.selectById(1L);
System.out.println("小李取出的价格:" + p1.getPrice());
// 2、小王
Product p2 = productMapper.selectById(1L);
System.out.println("小王取出的价格:" + p2.getPrice());
// 3、小李将价格加了50元,存入了数据库
p1.setPrice(p1.getPrice() + 50);
productMapper.updateById(p1);
// 4、小王将商品减了30元,存入了数据库
p2.setPrice(p2.getPrice() - 30);
int result = productMapper.updateById(p2);
if (result == 0) {// 更新失败,重试
// 重新获取数据
p2 = productMapper.selectById(1L);
// 更新
p2.setPrice(p2.getPrice() - 30);
productMapper.updateById(p2);
}
// 最后的结果
Product p3 = productMapper.selectById(1L);
System.out.println("最后的结果:" + p3.getPrice()); //price应为120
}
}
结果:
接下来我们看一下控制台里详细打印的过程:
(1)、小李取出的价格(2)、小王取出的价格
(3)、小李将价格加了50元,存入了数据库(修改数据是带上了version字段,此时version=1)
(4)、小王将商品减了30元,存入了数据库,但操作失败,原因是它使用verson=0检索不到当前数据,自然也就修改不了。
(5)、小王更新失败后重新查询数据,查询出的version为1
(6)、小王尝试更新数据,此时更新成功,版本version=2
(7)、查看最后结果
最后,我想要告诉大家的是,乐观锁的适用场景,当要更新一条记录的时候,希望这条记录没有被别人更新。好了,乐观锁就向大家介绍到这了,有不对的地方希望大家多多指教!😀