06乐观锁与悲观锁

news2024/10/6 18:26:11

乐观锁与悲观锁

悲观锁: 悲观锁比较适合插入数据,简单粗暴但是性能一般

乐观锁: 比较适合更新数据, 性能好但是成功率低(多个线程同时执行时只有一个可以执行成功),还需要访问数据库造成数据库压力过大

在这里插入图片描述

模拟乐观锁实现流程

第一步: 数据库中增加商品表t_product并插入一条数据

CREATE TABLE t_product(
id BIGINT(20) NOT NULL COMMENT '主键ID',
NAME VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名称',
price INT(11) DEFAULT 0 COMMENT '价格',
VERSION INT(11) DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY (id));
--插入一条数据
INSERT INTO t_product (id, NAME, price) VALUES (1, '外星人笔记本', 100);

第二步: 定义实体类Product和mapper接口ProductMapper

@Data
public class Product {
    private Long id;
    private String name;
    private Integer price;
    private Integer version;
}
@Repository
public interface ProductMapper extends BaseMapper<Product> {
}

第三步: 在测试方法中模拟小王小李同时获取到商品价格然后做修改操作

@Test
public void testConcurrentUpdate() {
    //小李取出的价格100
    Product p1 = productMapper.selectById(1L);
    System.out.println("小李取出的价格:" + p1.getPrice());
    //小王取出的价格100
    Product p2 = productMapper.selectById(1L);
    System.out.println("小王取出的价格:" + p2.getPrice());
    //小李将价格加了50元存入了数据库,此时商品价格150
    p1.setPrice(p1.getPrice() + 50);
    int result1 = productMapper.updateById(p1);
    System.out.println("小李修改结果:" + result1);
    //小王将商品减了30元存入了数据库,此时商品价格70
    p2.setPrice(p2.getPrice() - 30);
    int result2 = productMapper.updateById(p2);
    System.out.println("小王修改结果:" + result2);
    //老板查询商品价格发现是70,即小李的操作被小王覆盖了
    Product p3 = productMapper.selectById(1L);
    System.out.println("最后的结果:" + p3.getPrice());
}

Mybatis-Plus实现乐观锁

第一步: 数据库商品表t_product中添加version字段默认值是0

第二步: 在实体类的version属性上添加@Version注解表示该属性对应的字段是乐观锁版本号字段

@Data
public class Product {
    private Long id;
    private String name;
    private Integer price;
    @Version
    private Integer version;
}

第三步: 在config.MybatisPlusConfig配置类的MybatisPlusInterceptor插件对象中添加乐观锁插件对象OptimisticLockerInnerInterceptor

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    //添加分页插件对象
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    //添加乐观锁插件对象
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}

第四步: 在测类方法中测试乐观锁的效果

  • 在执行查询语句时同时获取当前记录的版本号
  • 在更新记录信息时同时在当前版本号的基础上加1,但是条件是版本号还是之前查询到的那个版本号,否则所有的更新操作都将失败
@Test
public void testConcurrentUpdate() {
    //小李取出的价格100
    //SELECT id,`name`,price,`version`FROM product WHERE id = 1;
    Product p1 = productMapper.selectById(1L);
    //小王取出的价格100
    //SELECT id,`name`,price,`version`FROM product WHERE id = 1;
    Product p2 = productMapper.selectById(1L);
    //小李将价格加了50元后存入了数据库,此时商品信息的版本号已经变为了1
    p1.setPrice(p1.getPrice() + 50);
	//update t_product set name = 外星人笔记本,price = 150,version = 1 where id = 1 and version = 0
    int result1 = productMapper.updateById(p1);
    //小王将商品减了30元,但是执行更新操作时发现商品信息的版本号与自己取出版本号不一致所以会更新失败
    //update t_product set name = 外星人笔记本,price = 70,version = 1 where id = 1 and version = 0
    p2.setPrice(p2.getPrice() - 30);
    int result2 = productMapper.updateById(p2);
    //商品最后的价格150,小王的更新操作失败了
    Product p3 = productMapper.selectById(1L);
    System.out.println("最后的结果:" + p3.getPrice());
}

优化: 如果小王更新失败就重新获取商品的版本号,然后再次执行更新的操作

@Test
public void testConcurrentVersionUpdate() {
    //小李取出的价格100
    Product p1 = productMapper.selectById(1L);
    //小王取出的价格100
    Product p2 = productMapper.selectById(1L);
    //小李将价格价格50
    p1.setPrice(p1.getPrice() + 50);
    productMapper.updateById(p1);
    //小王将价格减30
    p2.setPrice(p2.getPrice() - 30);
    int result = productMapper.updateById(p2);
    //result等于0表示更新失败,此时需要重新执行查询语句获取商品版本号并再次执行更新操作
    if(result == 0){
        p3 = productMapper.selectById(1L);
        p3.setPrice(p3.getPrice() - 30);
        //update t_product set name = 外星人笔记本,price = 120,version = 2 where id = 1 and version = 1
        productMapper.updateById(p3);
    }
    //最后商品的价格120
    Product p4 = productMapper.selectById(1L);
    System.out.println("老板看价格:" + p4.getPrice());
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1015406.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MySQL】基础SQL语句——表的操作

文章目录 一. 创建表二. 查看表结构三. 修改表3.1 修改表名或列名3.2 插入数据3.3 添加列3.4 修改列类型3.5 删除列 四. 删除表结束语 一. 创建表 create table table_name(field1 datatype,field2 datatype...) charset 字符集 collate 校验规则 engine 存储引擎; 创建表 fiel…

07通用枚举和表的代码生成器

通用枚举 通用枚举 如果表中的有些字段值是固定的例如性别(男或女),此时我们可以使用MyBatis-Plus的通用枚举来为属性赋值 需求: 在数据库表添加字段sex 第一步: 设置枚举类型,使用EnumValue注解将注解所标识的属性值存储到数据库中 // 枚举类型只要设置getter方法 Getter …

2023/09/15 qt day1

代码实现图形化界面 #include "denglu.h" #include "ui_denglu.h" #include <QDebug> #include <QIcon> #include <QLabel> #include <QLineEdit> #include <QPushButton> denglu::denglu(QWidget *parent): QMainWindow(p…

JavaScript-promise使用+状态

Promise 什么是PromisePromise对象就是异步操作的最终完成和失败的结果&#xff1b; Promise的基本使用&#xff1a; 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compati…

层次聚类分析

1、python语言 from scipy.cluster import hierarchy # 导入层次聚类算法 import matplotlib.pylab as plt import numpy as np# 生成示例数据 np.random.seed(0) data np.random.random((20,1))# 使用树状图找到最佳聚类数 Z hierarchy.linkage(data,methodweighted,metric…

时序预测 | MATLAB实现NGO-BiLSTM北方苍鹰算法优化双向长短期记忆网络时间序列预测

时序预测 | MATLAB实现NGO-BiLSTM北方苍鹰算法优化双向长短期记忆网络时间序列预测 目录 时序预测 | MATLAB实现NGO-BiLSTM北方苍鹰算法优化双向长短期记忆网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 时序预测 | MATLAB实现NGO-BiLSTM北方苍鹰算法优…

面对突如其来的 GC 问题如何下手解决

今天我们主要从一个实战案例入手分析面对突如其来的 GC 问题该如何下手解决。 想要下手解决 GC 问题&#xff0c;我们首先需要掌握下面这三种问题。 如何使用 jstat 命令查看 JVM 的 GC 情况&#xff1f; 面对海量 GC 日志参数&#xff0c;如何快速抓住问题根源&#xff1f; …

保密技术基础--北交大实验靶场2

由于第2、第3章的内部章节较少&#xff0c;所以我将其的体验感受一起写在这篇文章当中。 2.1 保密专用网络知识学习 这一小节也是一节的理论知识学习&#xff0c;学习过后有一个小测试&#xff0c;和第一章一样&#xff0c;学的知识和给的题目可以说是毫无关系。这一节的知识更…

VBA技术资料1-182

MF系列VBA技术资料 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-04属于定…

04_kibana 安装和配置指南

04_kibana 安装和配置指南 概述安装配置可能报错环境变量配置 概述 这个是干啥的呢&#xff1f; 目前我理解就是数据的展示 我们安装的目的是 请求访问ES&#xff0c; 如果没有安装完全可以使用postman代替 不过这个调试的时候有提示比较好&#xff0c; 所以我就安装了 安装…

【射频电路基础】第二章-谐振功率放大器

本书所用版本为:《射频电路基础》第二版&#xff08;赵建勋 邓军 著&#xff09; 网课详情见b站:《射频电路基础&#xff08;高频电子线路&#xff09;》 本书的笔记以书本和手写笔记结合为主。 文章目录 第二章 谐振功率放大器1. 谐振功率放大器的工作原理2. 谐振功率放大器…

Android kotlin开源项目-功能标题目录

目录 一、BRVAH二、开源项目1、RV列表动效&#xff08;标题目录&#xff09;2、拖拽与侧滑&#xff08;标题目录&#xff09;3、数据库&#xff08;标题目录&#xff09;4、树形图(多级菜单)&#xff08;标题目录&#xff09;5、轮播图与头条&#xff08;标题目录&#xff09;6…

蓝桥杯 题库 简单 每日十题 day2

01 卡片 题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 小蓝有很多数字卡片&#xff0c;每张卡片上都是数字 0 到 9。 小蓝准备用这些卡片来拼一些数&#xff0c;他想从 1 开始拼出正整数&#xff0c;每拼一个&a…

红黑树(思维导图详解版)

目录 资源已上传 实现代码 测试代码 资源已上传 部分图片 实现代码 注意判断是否为红黑树的代码实现&#xff0c;实现代码中红黑树的删除 #pragma once #include<iostream> using namespace std;enum Color_Type {Red,Black };template<class K,class V> str…

【计算机视觉】Vision Transformers算法介绍合集(一)

文章目录 一、Vision Transformer二、Swin Transformer三、Detection Transformer四、Data-efficient Image Transformer五、self-DIstillation with NO labels六、Deformable DETR七、Compact Convolutional Transformers八、NesT九、Pyramid Vision Transformer十、Dense Pre…

什么是MQ消息队列及四大主流MQ的优缺点(个人网站复习搬运)

什么是&#xff2d;&#xff31;消息队列及四大主流&#xff2d;&#xff31;的优缺点 小程序要上一个限时活动模块&#xff0c;需要有延时队列&#xff0c;从网上了解到用RabbitMQ可以解决&#xff0c;就了解了下 MQ 并以此做记录。 一、为什么要用 MQ 核心就是解耦、异步和…

算法笔记—多数相加

首先&#xff0c;我们要引入一个一道题目1. 两数之和 - 力扣&#xff08;LeetCode&#xff09; 两数之和 其实这道题很简单&#xff0c;但是&#xff0c;可以使用内嵌循环来进行遍历&#xff0c;找到符合要求的数据&#xff0c;返回下标即可。 但今天提供另一个方法&#xff…

劳务管理 视频监控 项目版智慧工地管理系统源码

智慧工地管理系统将人工智能技术、传感器技术、虚拟现实技术等更多高新技术嵌入到建筑、机器、人员佩戴的设备、工地出入口大门等各种物体中&#xff0c;广泛互联形成“物联网技术”&#xff0c;再与“互联网技术”融合&#xff0c;完成项目管理利益相关者与项目施工现场的融合…

数据仓库模型设计V2.0

一、数仓建模的意义 数据模型就是数据组织和存储方法&#xff0c;它强调从业务、数据存取和使用角度合理存储数据。只有将数据有序的组织和存储起来之后&#xff0c;数据才能得到高性能、低成本、高效率、高质量的使用。 高性能&#xff1a;良好的数据模型能够帮助我们快速查询…

考研算法47天:01背包

问题描述 算法详细步骤 代码随想录 (programmercarl.com) ac代码 #include <iostream> using namespace std; int bag[1001]; int bagMax[1001]; int bagvalue[1001]; int main(){int n,v;cin>>n>>v;for(int i0;i<n;i){cin>>bag[i]>>bagva…