当前位置: 首页 > news >正文

超卖问题的乐观锁与悲观锁

悲观锁:认为线程安全问题一定会发生,因此在操作数据之前先获取锁,确保线程串行执行。例如SynchronizedLock都属于悲观锁认为线程安全问题一定会发生,因此在操作数据之前先获取锁,确保线程串行执行。

乐观锁:认为线程安全问题不一定会发生,因此不加锁,只在更新数据时去判断(所以乐观锁只能在有更新操作的地方使用)有没有其它线程对数据做了修改。如果没有修改则认为是安全的,自己才更新数据。如果已经被其它线程修改说明发生了安全问题,此时可以重试或异常(一句话:判断之前查询得到的数据是否有被修改过)

悲观锁就不多说了,乐观锁有两种实现方式:

  1. 版本号法
    更新一次数据就更新一次版本号,每次更新前判断版本号是否相同,就可以确定是否更新过
  2. CAS法:
    我的理解是,设置一个预期值,达到预期值后就不能继续操作了。

以下有一个来自黑马点评的案例。我们采用了CAS法设置库存预期值为0,当发现库存小于1时就要停止操作了。每个线程会在更新前进行判断

@Service public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService { @Resource private ISeckillVoucherService seckillVoucherService; @Resource private RedisIdWorker redisIdWorker; @Override @Transactional public Result seckillVoucher(Long voucherId) { //查询优惠券 SeckillVoucher voucher = seckillVoucherService.getById(voucherId); //判断秒杀是否开始 LocalDateTime beginTime = voucher.getBeginTime(); LocalDateTime endTime = voucher.getEndTime(); if(beginTime.isAfter(LocalDateTime.now())){ return Result.fail("秒杀尚未开始"); } //判断秒杀是否结束 if(endTime.isBefore(LocalDateTime.now())){ return Result.fail("秒杀已结束"); } //库存是否充足 if (voucher.getStock() < 1) { return Result.fail("库存不足"); } //扣减库存 boolean success = seckillVoucherService.update() .setSql("stock = stock - 1") .eq("voucher_id", voucherId) .gt("stock",0) .update(); if(!success){ return Result.fail("扣减库存失败"); } //创建订单 VoucherOrder voucherOrder = new VoucherOrder(); //订单id long orderId = redisIdWorker.nextId("order"); //用户id Long userId = UserHolder.getUser().getId(); voucherOrder.setId(orderId); voucherOrder.setUserId(userId); //代金券id voucherOrder.setVoucherId(voucherId); save(voucherOrder); //返回订单id return Result.ok(orderId); }
http://www.jsqmd.com/news/567720/

相关文章:

  • 2026年 温度控制器厂家推荐排行榜:机械型/KSD301/突跳式电木陶瓷/小体积塑铁壳电源温控器,精准控温与耐用品质深度解析 - 品牌企业推荐师(官方)
  • 3DGS实战:从Windows到Colab的完整复现与避坑指南
  • Karp的21个NPC问题:从理论到实践的经典探索
  • IDEA批量替换的隐藏技巧:除了Ctrl+R,你还可以试试这个Java文件流方案
  • Servlet 简介
  • 大模型推理慢?全靠 KV Cache 提速几十倍!大模型推理优化教程(非常详细),从入门到精通,收藏这一篇就够了!
  • 2026贵州凯里辣椒面选型指南:盈泽盛3大硬指标 - 精选优质企业推荐榜
  • Simulink SVPWM模块输出对不上?别慌,可能是这两个参数没设对(附24V电机FOC仿真案例)
  • 从Apollo到你的项目:深入解读自动驾驶中Frenet坐标系的实际应用与工程考量
  • ESP32 CMakeLists.txt配置避坑指南:为什么加了PRIV_REQUIRES driver反而编译失败?
  • 一文看懂AI Agent日志重构任务的行动计划
  • Go语言中的JSON处理:从入门到精通
  • 高效解决E-Hentai图库下载难题:实用下载工具全攻略
  • Overleaf-Workshop:在VSCode中实现Open Overleaf项目的无缝协作与高效管理
  • 手把手教你用华为云ModelArts免费GPU跑自己的模型(附OBS避坑指南)
  • uni-app 三端上线全流程指南:H5 / 小程序 / App 完整发布手册
  • MCP2515调试血泪史:发送邮箱占满、总线错误,我的排查思路与硬件踩坑实录
  • 告别调参烦恼!SimAM注意力机制实战:在YOLOv5/v8中轻松涨点(保姆级教程)
  • 老生常谈:聊聊mysql幻读问题?
  • 实战向 Python 汽车推荐系统 Django框架 可视化 协同过滤算法 数据分析 大数据 机器学习(建议收藏)✅
  • 零基础入门c/c++:在快马平台一键获取vscode环境配置指南
  • 3大核心功能打造智能游戏体验:League-Toolkit从入门到精通指南
  • 2026国内LMS厂商全景洞察:一张图覆盖大集团到中小企业
  • 3步搞定Whisper-WebUI部署:从零搭建专业级语音转字幕平台
  • ArcGIS中高效提取面状SHP文件坐标的3种实用方法
  • 开发提效新组合:用Cursor编写核心逻辑,快马平台一键生成完整企业级项目
  • 如何让旧款Mac焕发新生:OpenCore Legacy Patcher完整指南
  • ARM架构下独占访问指令(LDXR/STXR)失效的实战排查与优化指南
  • 网站SEO免费优化有哪些常见的误区
  • 颠覆传统:智能网页捕获工具重新定义长截图体验