中山模板建站代理漳州网站建设厂家

张小明 2026/1/13 7:35:16
中山模板建站代理,漳州网站建设厂家,必应网站收录提交入口,网上推广网站MyBatis-Plus的乐观锁与悲观锁 锁机制的必要性模拟并发更新冲突 悲观锁模拟实现悲观锁 乐观锁模拟实现乐观锁 MyBatis-Plus 的乐观锁是基于版本号机制实现的非阻塞式并发控制方案#xff0c;对应用层乐观锁逻辑提供轻量化封装#xff1b;悲观锁则整合数据库原生行锁 / 表锁机…MyBatis-Plus的乐观锁与悲观锁锁机制的必要性模拟并发更新冲突悲观锁模拟实现悲观锁乐观锁模拟实现乐观锁MyBatis-Plus 的乐观锁是基于版本号机制实现的非阻塞式并发控制方案对应用层乐观锁逻辑提供轻量化封装悲观锁则整合数据库原生行锁 / 表锁机制在操作数据时预先锁定资源以阻塞冲突操作二者均用于保障并发更新场景下的数据一致性。下面详细介绍锁机制的必要性以及 MyBatis-Plus 的乐观锁与悲观锁内容。锁机制的必要性首先我们假设一个业务场景探究一下锁机制的必要性某商品成本价 80 元当前售价 100 元老板先后下达两条调价指令指令 1给小李将商品价格上调 50 元小李因事务耽搁延迟 1 小时执行指令 2给小王1 小时后老板调整策略要求将商品价格下调 30 元小王立即执行。无锁下的执行过程小李和小王均从数据库读取到初始价格 100 元小李执行操作100 50 150 元写入数据库小王执行操作100 - 30 70 元写入数据库覆盖小李的更新结果最终商品价格为 70 元低于成本价 80 元。若该商品短时间售出 1000 件将造成约 10000 元的直接经济损失。我们将上述场景进行复原模拟模拟并发更新冲突首先是在数据库中新增商品表CREATETABLEproduct(idBIGINT(20)NOTNULLCOMMENT主键ID,NAMEVARCHAR(30)NULLDEFAULTNULLCOMMENT商品名称 ,priceINT(11)DEFAULT0COMMENT价格 ,PRIMARYKEY(id));添加数据INSERTINTOproduct(id,NAME,price)VALUES(1,牛奶,100);添加实体类DataNoArgsConstructorAllArgsConstructorpublicclassProduct{privateLongid;privateStringname;privateIntegerprice;privateIntegerversion;}添加 Mapper 接口publicinterfaceProductMapperextendsBaseMapperProduct{}并发更新测试SpringBootTestpublicclassMybatisConfigTest{AutowiredprivateProductMapperproductMapper;TestpublicvoidtestUpdate(){Productp1productMapper.selectById(1L);System.out.println(小李取出的价格p1.getPrice());Productp2productMapper.selectById(1L);System.out.println(小王取出的价格p2.getPrice());p1.setPrice(p1.getPrice()50);intresult1productMapper.updateById(p1);System.out.println(小李修改结果p1.getPrice());p2.setPrice(p2.getPrice()-30);intresult2productMapper.updateById(p2);System.out.println(小王修改结果p2.getPrice());Productp3productMapper.selectById(1L);System.out.println(最后的结果p3.getPrice());}}执行结果在多线程 / 多进程并发操作数据库的场景中若缺乏锁机制约束“读取 - 更新” 操作缺乏原子性约束后执行的更新覆盖先执行的结果极易引发更新丢失问题破坏数据一致性。数据库锁机制正是解决此类问题的核心手段。悲观锁悲观锁是基于悲观并发假设的数据库并发控制策略其核心实现依赖 InnoDB 存储引擎原生的SELECT ... FOR UPDATE语法。MyBatis-Plus 完全兼容数据库层面的悲观锁实现逻辑只需在自定义查询 SQL 中为目标数据查询语句拼接 FOR UPDATE 子句即可借助数据库的锁机制实现悲观锁效果。SELECT ... FOR UPDATE语句的执行逻辑可拆解为 “数据查询 排他行锁施加”执行该语句时数据库首先检索出符合查询条件的记录同时为这些记录施加排他行锁X 锁该锁的生命周期与当前数据库事务强绑定仅在事务提交或回滚后释放。在此期间其他事务若尝试对锁定记录执行加排他锁的操作会被阻塞直至锁释放。需要注意的是 SELECT … FOR UPDATE 锁机制的生效前提仅在显式开启的事务内有效若未通过 BEGIN/START TRANSACTION 或框架注解如 Spring Transactional显式启动事务MySQL 会将单条 SELECT … FOR UPDATE 语句视为独立事务执行后立即自动提交导致锁被瞬间释放无法起到悲观锁的并发控制作用。模拟实现悲观锁创建 Mapper 接口自定义 SQL 悲观锁查询方法显式添加 FOR UPDATEpublicinterfaceProductMapperextendsBaseMapperProduct{/** * 悲观锁查询 */Select(SELECT * FROM product WHERE id #{id} FOR UPDATE)ProductselectByIdForUpdate(Param(id)Longid);}Service 层接口publicinterfaceProductServiceextendsIServiceProduct{booleanliXiaoAddPrice(Longid);booleanxiaoWangReducePrice(Longid);}Service 层实现类实现操作加悲观锁和事务ServicepublicclassProductServiceImplextendsServiceImplProductMapper,ProductimplementsProductService{// 小李操作Transactional(rollbackForException.class)publicbooleanliXiaoAddPrice(Longid){// 悲观锁查询锁定行直到事务结束ProductproductbaseMapper.selectByIdForUpdate(id);if(productnull){returnfalse;}try{System.out.println(小李其他事务耽搁10秒后再调价...);Thread.sleep(10000);}catch(InterruptedExceptione){Thread.currentThread().interrupt();thrownewRuntimeException(小李操作中断,e);}product.setPrice(product.getPrice()50);booleanresultbaseMapper.updateById(product)0;System.out.println(小李调价完成当前价格product.getPrice());returnresult;}// 小王操作Transactional(rollbackForException.class)publicbooleanxiaoWangReducePrice(Longid){// 悲观锁查询ProductproductbaseMapper.selectByIdForUpdate(id);if(productnull){returnfalse;}product.setPrice(product.getPrice()-30);booleanresultbaseMapper.updateById(product)0;System.out.println(小王调价完成当前价格product.getPrice());returnresult;}加悲观锁进行模拟测试AutowiredprivateProductServiceproductService;/** * 加悲观锁模拟小李和小王同时操作商品价格 */TestpublicvoidtestLiXiaoAndXiaoWang()throwsInterruptedException{LongproductId1L;System.out.println(初始价格productService.getById(productId).getPrice());// 小李线程ThreadliXiaoThreadnewThread(()-productService.liXiaoAddPrice(productId));// 小王线程ThreadxiaoWangThreadnewThread(()-productService.xiaoWangReducePrice(productId));// 同时启动两个线程模拟同时操作System.out.println( 小李和小王同时开始操作 );liXiaoThread.start();xiaoWangThread.start();// 等待两个线程执行完成liXiaoThread.join();xiaoWangThread.join();// 查询最终价格ProductfinalProductproductService.getById(productId);System.out.println(最终商品售价finalProduct.getPrice()元);}操作效果乐观锁乐观锁Optimistic Locking是基于 “并发操作中数据冲突发生概率极低” 的乐观并发假设设计的非阻塞式并发控制机制核心目标是保障多线程 / 多进程并发更新场景下的数据一致性避免更新操作覆盖其他并发事务产生的有效数据。与悲观锁通过数据库原生锁机制预先对数据资源加锁、阻塞其他并发事务的冲突操作不同乐观锁本质是无预锁定的冲突检测与冲突解决机制。其不依赖数据库层面的主动加锁来限制并发操作而是在数据更新请求提交至数据库持久化层的最终阶段通过版本号、时间戳等校验手段检测是否存在并发更新冲突若检测到冲突则由业务层按需采取重试、终止操作等策略处理以保证数据更新的正确性。核心执行逻辑以主流的版本号机制为例读取阶段在事务上下文内读取目标数据时同步获取该数据关联的版本标识如version字段的当前值仅用于记录版本信息用于后续校验业务处理阶段基于读取到的数据及版本值执行业务逻辑处理该阶段仍保持无锁状态其他并发事务对该数据的读取、操作不受任何阻塞更新校验与执行阶段向数据库提交更新请求时SQL 进行版本校验仅当数据库中该数据的当前版本值与事务读取阶段获取的版本值完全一致时才原子性执行更新操作若版本校验不通过则判定存在并发更新冲突此时由业务层按需执行重试、终止事务、返回冲突提示等策略处理。模拟实现乐观锁数据库层面添加 version 字段默认值为0ALTERTABLEproductADDCOLUMNversionINTNOTNULLDEFAULT0COMMENT乐观锁版本号;实体类层面标记 version 字段DataNoArgsConstructorAllArgsConstructorpublicclassProduct{privateLongid;privateStringname;privateIntegerprice;VersionprivateIntegerversion;}添加乐观锁插件配置ConfigurationpublicclassMybatisPlusConfig{BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptornewMybatisPlusInterceptor();//添加分页插件interceptor.addInnerInterceptor(newPaginationInnerInterceptor(DbType.MYSQL));//添加乐观锁插件interceptor.addInnerInterceptor(newOptimisticLockerInnerInterceptor());returninterceptor;}}SpringBootTestpublicclassMybatisConfigTest{AutowiredprivateProductMapperproductMapper;/** * 乐观锁 */TestpublicvoidtestConcurrentVersionUpdate(){Productp1productMapper.selectById(1L);Productp2productMapper.selectById(1L);p1.setPrice(p1.getPrice()50);intresult1productMapper.updateById(p1);System.out.println(小李修改的结果p1.getPrice());p2.setPrice(p2.getPrice()-30);intresult2productMapper.updateById(p2);System.out.println(小王修改的结果p2.getPrice());if(result20){p2productMapper.selectById(1L);p2.setPrice(p2.getPrice()-30);result2productMapper.updateById(p2);}System.out.println(小王修改重试的结果p2.getPrice());Productp3productMapper.selectById(1L);System.out.println(老板看价格p3.getPrice());}}
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

网站模板下载软件小红书app下载安装

Git commit回退代价大?镜像支持快照回滚 在AI模型的日常开发与部署中,一个看似简单的问题常常让工程师头疼:一次更新出错后,如何快速、安全地回到“昨天还能跑”的状态? 尤其是在文本转语音(TTS&#xff09…

张小明 2026/1/12 7:43:13 网站建设

动态图表网站1688黄页网女性

AI元人文构想:悟空来路与关山——岐金兰人机对话记录四篇(2025.9.19)七绝悟空路——余溪回望水潺潺,石镜磨云迹自环。嬉斗长天撩一线,悟空来路与关山。主篇:《AI元人文之路:从思考外包到意义主权…

张小明 2026/1/12 7:43:06 网站建设

网站建设只有一个空间吗做相册哪个网站好用吗

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

张小明 2026/1/12 7:42:56 网站建设

大型百度云网站建设山东平台网站建设设计

TDengine Java 连接器入门指南 一、什么是 TDengine Java 连接器? TDengine Java 连接器(taos-jdbcdriver)是一个让 Java 程序能够连接和操作 TDengine 时序数据库的工具包。就像你需要一把钥匙才能打开门一样,Java 程序需要这个…

张小明 2026/1/12 7:42:49 网站建设

福州企业建设网站采购管理系统软件

在数字化时代,程序员早已成为职场 “刚需群体”—— 据统计,国内程序员从业者超 2000 万,高校计算机相关专业年毕业生突破 100 万。但与之形成鲜明对比的是,网络安全领域(含黑客技术相关岗位)人才缺口长期维…

张小明 2026/1/12 7:42:41 网站建设

个人网站如何赚钱温州网站提升排名

2025年,战略咨询在推动行业标准演进方面发挥着重要作用。针对当前市场需求的变化,咨询公司为企业提供定制化的解决方案,使之适应不断更新的行业标准。通过深入市场分析,战略咨询不仅帮助企业识别新的竞争机会,还有效提…

张小明 2026/1/12 20:54:03 网站建设