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

多线程下 到底是事务内部开启锁 还是先加锁再开启事务?

前言

不知大家是否有观察到一个最常见的错误:

先开启事务,然后针对资源加锁,操作资源,然后释放锁,最后提交事务

你是否发现了在这样的场景下会出现并发安全的问题?
(提示:一个线程A在事务内部释放锁,另一个线程B拿到了锁,线程B看不到线程A的操作 导致 线程B 重复执行线程A已经对资源进行的操作)

用一个业务场景去说明

用一个电商系统的订单处理场景来具体说明这个“事务没有完全被锁包住”会导致的问题。

需求: 用户点击“下单”按钮后,后台要:

检查该用户是否已经提交过该订单(防重复下单)

如果没有,就创建订单

并扣减库存

错误的业务代码:

@Transactional
public void createOrder(String userId, String orderNo) {if (!orderService.hasOrdered(orderNo)) {synchronized (("lock:" + orderNo).intern()) {// 锁内逻辑// 此处加锁}// 锁释放了,但事务还没提交orderService.save(orderNo);  // 保存订单productService.decreaseStock(); // 扣减库存}
}

1、线程A

开启事务

查询:是否已下单?→ 查询不到(因为数据库未提交)

执行下单逻辑:准备插入订单

!! 锁在事务内部,提前释放

事务还没提交!

2、线程B

紧接着执行相同操作

开启事务

查询:是否已下单?→ 同样查询不到(线程A没提交)

执行下单逻辑:插入重复订单、扣减库存

提交事务

最终结果

因为 数据库在**“读已提交**”隔离级别下,线程B看不到线程A未提交的插入

又因为加锁只包了业务逻辑而不是整个事务范围

所以锁一旦提前释放,线程B就能并发进来了
线程A和线程B都成功下了单

结果就是 重复支付 / 重复下单

改进

public void createOrderSafe(String userId, String orderNo) {synchronized (("lock:" + orderNo).intern()) { // 线程B被阻塞doCreateOrder(userId, orderNo);           // 锁保护整个事务 内部是本地事务}
}

或者微服务中 使用redis分布式锁

RLock lock = redissonClient.getLock("order:" + orderNo);
if (lock.tryLock()) {try {// 事务中执行订单判断与插入} finally {lock.unlock(); // 锁直到事务结束才释放}
}

总结

锁放在事务外部

http://www.xdnf.cn/news/1037287.html

相关文章:

  • 《人工智能时代与人类价值》读书简要笔记
  • [CVPR 2025] DeformCL:基于可变形中心线的3D血管提取新范式
  • Docker全平台安装指南:从零到一构建容器化环境(满级版)
  • GDI+ 中与GDI32取图形区域函数对比CreateEllipticRgn/CreatePolygonRgn
  • g++ a.cpp -o a ‘pkg-config --cflags --libs opencv4‘/usr/bin/ld: 找不到 没有那个文件或目录
  • [智能客服project] AI提示词配置 | 主协调器 | 闲鱼协议工具
  • PX4无人机|MID360使用FAST_LIO,实现自主定位及定点——PX4无人机配置流程(五)
  • Vue Methods 实现原理详解
  • 【数据集成与ETL 04】dbt实战指南:现代化数据转换与SQL代码管理最佳实践
  • 一个前端正则校验引发的问题
  • 马上行计划管理后端架构
  • 深度分析Javascript中的Promise
  • 动态多目标进化算法:基于迁移学习的动态多目标遗传算法Tr-NSGA-II求解CEC2015,提供完整MATLAB代码
  • python基础与数据类型
  • C# 枚 举(枚举)
  • Python Day51
  • pyspark非安装使用graphframes
  • PHP+mysql雪里开轻量级报修系统 V1.0Beta
  • Laravel 从版本 5 到 12 每个版本都引入了一些新的特性、改进和弃用的功能
  • rt-thread的定时器驱动(裸机版本)记录.
  • Flutter JSON解析全攻略:使用json_serializable实现高效序列化
  • java设计模式[1]之设计模式概览
  • 免费电子印章生成工具,可在线设计印章
  • TLSF 内存分配器
  • 通达信跟老庄追涨停指标公式
  • 【大模型分布式训练】多卡解决单卡训练内存不足的问题
  • Python学习笔记面向对象编程
  • Python 中的 `lru_cache` 详解
  • 固件签名技术深度解析:HSM模块如何守护设备安全,CAS系统如何赋能产业升级
  • pytest的装饰器`pytest.mark.parametrize` 和 `@pytest.mark.smoke`区别