乐观锁实现库存控制

一、什么是乐观锁?


乐观锁是一种基于版本控制的并发控制机制。在乐观锁的思想中,认为数据访问冲突的概率很低,因此不加锁直接进行操作,但在更新数据时会进行版本比对,以确保数据的一致性。

乐观锁的原理主要基于版本号或时间戳来实现。在每次更新数据时,先获取当前数据的版本号或时间戳,然后在更新时比对版本号或时间戳是否一致,若一致则更新成功,否则表示数据已被其他线程修改,更新失败。

在Java中,常见的乐观锁实现是使用Atomic类,例如AtomicInteger、AtomicLong等。这些类提供了原子操作,可以确保对共享资源的更新操作是原子性的,从而避免了锁的开销和线程等待,另外,CAS(Compare-And-Swap)是实现乐观锁的核心算法,它通过比较内存中的值是否和预期的值相等来判断是否存在冲突。如果存在,则返回失败;如果不存在,则执行更新操作。Java中提供了AtomicInteger、AtomicLong、AtomicReference等原子类来支持CAS操作。

二、乐观锁适用于什么场景

写操作较少:在这种场景下,多个事务或线程大部分时间都在读取数据,而写操作的频率相对较低。乐观锁能够减少锁的持有时间,允许多个事务或线程同时读取数据,而不会相互阻塞。
数据冲突较少:如果数据更新操作之间的冲突较少,即多个事务或线程同时更新同一份数据的概率较低,那么乐观锁能够发挥很好的性能。因为即使偶尔出现冲突,也只是在更新数据时才会被检测到,而不需要在整个数据处理过程中都锁定资源。
重试成本较低:乐观锁在检测到冲突时会回滚事务或提示冲突,需要客户端重新尝试更新操作。因此,如果重试的成本较低(例如,重试不会导致大量计算或I/O操作),那么使用乐观锁是合适的。
系统能够容忍一定程度的失败:由于乐观锁在更新数据时可能会因为版本冲突而失败,因此系统需要能够处理这种失败情况。如果系统能够容忍一定程度的失败(例如,通过重试或其他补偿机制来恢复),那么使用乐观锁是可行的。

三、乐观锁优缺点


优点:
高并发高吞吐:乐观锁不会阻塞其他事务的读取操作,只在提交时检查数据是否被修改,因此可以提供更好的并发性能。
无锁操作:乐观锁不需要显式地获取和释放锁,减少了锁竞争和上下文切换的开销。
无死锁风险:由于乐观锁不会阻塞其他事务的访问,因此不会出现死锁的情况。
缺点:
冲突处理复杂:由于乐观锁不会阻塞其他事务,因此在提交时需要检查数据是否被其他事务修改,如果发现冲突,需要回滚事务或重新尝试操作,这增加了冲突处理的复杂性。
数据一致性风险:乐观锁假设并发冲突较少,因此可能存在数据一致性的风险。如果多个事务同时对同一数据进行修改,可能会导致数据不一致的情况。
需要额外字段:为了实现乐观锁,通常需要在数据表中添加额外的版本号或时间戳字段,这增加了存储空间的需求。
处理不当造成死循环风险:在大多数业务中乐观锁更新失败都会进行自旋,如果没有控制好自旋退出逻辑可能会造成递归死循环问题。

四、使用示例

简单业务代码:

    @Override
    public String test1() {
        SumDO sumDO = sumMapper.selectById(1);
        if (sumDO.getSum() <= 0) {
            log.info(sumDO.getSum() + ":库存不足");
            return "库存不足";
        }
        Boolean update = sumMapper.updateByVersion(sumDO.getId(), sumDO.getVersion(), sumDO.getVersion() + 1);
        if (update) {
            System.out.println(update + ":购买成功,剩余数量 = " + (sumDO.getSum() - 1));
        } else {
            System.out.println(update + ":当前人数过多,修改失败 = " + (sumDO.getSum()));
        }
        return update.toString();
    }

数据库修改语句

    @Update("UPDATE `sum` SET `sum` = sum  - 1 , version = #{newVersion} WHERE `id` = #{id} and version = #{version}")
    Boolean updateByVersion(int id, int version,int newVersion);

五、验证结果

初始数据库数据 5个库存,版本号为1

通过20个线程并发测试

结果五个全部卖出

 数据库库存为0,未产生超卖的情况

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring IOC 控制反转(注解版)

Spring IOC 控制反转 文章目录 Spring IOC 控制反转一、前言什么是控制反转&#xff08;IOC&#xff09;什么是依赖注入&#xff08;DI&#xff09; 二、介绍 IOC2.1 传统思想代码2.2 解决方案2.3 IOC思想代码2.4 IOC 使用&#xff08;Autowired依赖注入&#xff09;2.5 IOC 优…

Service方法增加@Asyn注解后导致bean无法找到 NoSuchBeanDefinitionException

Service方法增加Asyn注解后导致bean无法找到 NoSuchBeanDefinitionException 场景处理方法原因 场景 首先确认的是Service添加了Service或Component等注解&#xff0c;另外也增加了ComponentScan确定扫描的包路径是包含对应Service的&#xff0c;但就是无法找到这个bean。 通…

从艳彩山水到艳彩艺术 薛永年:郭泰来艳彩艺术填补了中国美术史的空白

薛永年先生 自6月12日开展以来&#xff0c;郭泰来现代艺术大展杭州如火如荼地进行着&#xff0c;吸引了众多艺术爱好者和专业人士前往。毫不夸张地说&#xff0c;总统和清洁工人都能在他的作品中找到自己心中的那一块共振带并与之产生强烈的共鸣&#xff0c;这便是郭泰来先生的…

Vector 例题

例题一&#xff1a; 下面这个代码输出的是( ) &#xfeff;#include <iostream> #include <vector> using namespace std; int main(void) { vector<int>array; array.push_back(100); array.push_back(300); array.push_back(300); array.push_back(300); a…

Python学习笔记16:进阶篇(五)异常处理

异常 在编程中&#xff0c;异常是指程序运行过程中发生的意外事件&#xff0c;这些事件通常中断了正常的指令流程。它们可能是由于错误的输入数据、资源不足、非法操作或其他未预料到的情况引起的。Python中&#xff0c;当遇到这类情况时&#xff0c;会抛出一个异常对象&#…

34.构建核心注入代码

上一个内容&#xff1a;33.获取入口点 以 33.获取入口点 它的代码为基础进行修改 实现的功能是把LoadLibrary函数注入到目标进程实现加载我们的模块。LoadLibrary只有有程序使用过了它的代码就会加载到内存中&#xff08;因为动态链接库是内存加载&#xff09;就是a程序要用L…

QThread 与QObject::moveToThread在UI中的应用

1. QThread的两种用法 第一种用法就是继承QThread&#xff0c;然后覆写 virtual void run()&#xff0c; 这种用法的缺点是不能利用信号槽机制。 第二种用法就是创建一个线程&#xff0c;创建一个对象&#xff0c;再将对象moveToThread, 这种可以充分利用信号槽机制&#xff…

Polyp-DDPM: Diffusion-Based Semantic Polyp Synthesis for Enhanced Segmentation

Polyp- ddpm:基于扩散的语义Polyp合成增强分割 摘要&#xff1a; 本研究介绍了一种基于扩散的方法Polyp-DDPM&#xff0c;该方法用于生成假面条件下息肉的逼真图像&#xff0c;旨在增强胃肠道息肉的分割。我们的方法解决了与医学图像相关的数据限制、高注释成本和隐私问题的挑…

尚硅谷大数据技术ClickHouse教程-笔记01【ClickHouse单机安装、数据类型】

视频地址&#xff1a;一套上手ClickHouse-OLAP分析引擎&#xff0c;囊括Prometheus与Grafana_哔哩哔哩_bilibili 01_尚硅谷大数据技术之ClickHouse入门V1.0 尚硅谷大数据技术ClickHouse教程-笔记01【ClickHouse单机安装、数据类型】尚硅谷大数据技术ClickHouse教程-笔记02【表引…

Comfy UI使用最新SD3模型,并解决报错‘NoneType‘ object has no attribute ‘tokenize‘【实测可行】

解决Comfy UI使用最新SD3模型报错’NoneType’ object has no attribute ‘tokenize’ 前几天SD3发布了&#xff0c;所以想着尝尝鲜&#xff0c;便去下载了SD3来玩一玩。使用的是Comfy UI而不是Stable Diffusion UI&#xff0c;这是一个比SD UI更加灵活的UI界面&#xff0c;使用…

内容安全复习 4 - 深度生成模型

文章目录 概述经典算法自回归模型&#xff08;Autoregressive model&#xff09;变分自编码器&#xff08;VAE&#xff09;生成对抗网络&#xff08;GAN&#xff09;扩散模型&#xff08;Diffusion model&#xff09;总结 应用 概述 深度生成模型是一类使用深度学习技术构建的…

L55--- 257.二叉树的所有路径(深搜)---Java版

1.题目描述 2.思路 &#xff08;1&#xff09;因为是求二叉树的所有路径 &#xff08;2&#xff09;然后是带固定格式的 所以我们要把每个节点的整数数值换成字符串数值 &#xff08;3&#xff09;首先先考虑根节点&#xff0c;也就是要满足节点不为空 返回递归的形式dfs(根节…

数字内容“遍地开花”,AI技术如何创新“造梦”?

文 | 智能相对论 作者 | 陈泊丞 这是春晚舞台西安分会场《山河诗长安》的一幕&#xff1a;“李白”现世&#xff0c;带领观众齐颂《将进酒》&#xff0c;将中国人骨子里的豪情与浪漫演绎得淋漓尽致。 这又是浙江义乌商品市场里的另一幕&#xff1a;只会说几个英文单词的女老板…

入门Ansible常用模块

自动化运维Devops-Ansible Ansible是新出现的自动化运维工具&#xff0c;基于Python 开发&#xff0c;集合了众多运维工具&#xff08;puppet 、cfengine、chef、func、fabric&#xff09;的优点&#xff0c;实现了批量系统配置 、批量程序部署、批量运行命令 等功能。Ansible…

小程序 如何支付后获取 Unionid

接口说明 接口英文名 getPaidUnionid 功能描述 该接口用于在用户支付完成后&#xff0c;获调用本接口前需要用户完成支付&#xff0c;用户支付完成后&#xff0c;取该用户的 UnionId&#xff0c;无需用户授权。本接口支付后的五分钟内有效。 注意事项 调用前需要用户完成…

直播websocket签名signature字段生成逻辑,一步一步带你研究学习

现在每个直播的链接都要签名字段才可以校验成功&#xff0c;所以需要开始debug逻辑&#xff0c;研究一下这个加密的签名字段哪里来的&#xff0c;先找到这个发送请求的js代码在哪里&#xff1a; 找到发送websocket的地方了&#xff0c;看了一下_getSocketParams这就是获取请求参…

String(C++)

文章目录 前言文档介绍经典题目讲解HJ1 字符串最后一个单词的长度 模拟实现框架构造函数析构函数迭代器c_str()赋值size()capacity()reserveempty()[ ]访问front/backpush_backappendoperatorinsert一个字符insert一个字符串eraseswapfind一个字符find一个字符串substr()clear(…

超级会员卡积分收银系统源码 带完整的安装代码包以及搭建部署教程

系统概述 超级会员卡积分收银系统源码是一款专为商业运营打造的综合性软件解决方案。它集成了会员卡管理、积分管理、收银管理等多种功能&#xff0c;旨在为企业提供高效、便捷、准确的运营管理工具。 该系统源码采用先进的技术架构&#xff0c;具有良好的稳定性和扩展性&…

Python火焰锋动力学和浅水表面波浪偏微分方程

&#x1f3af;要点 &#x1f3af;流图可视化正弦余弦矢量场 | &#x1f3af;解空间变化边界条件二维拉普拉斯方程 | &#x1f3af;解圆柱坐标系标量场 | &#x1f3af;解一维泊松方程 | &#x1f3af;解二维扩散方程 | &#x1f3af;解火焰锋的动力学偏微分方程 | &#x1f3a…

自动备份SQL Server数据库,试试这4种方法!

各种规模的企业都使用 SQL 数据库来存储数据。因此&#xff0c;备份 SQL Server 数据库对于确保数据安全并在发生灾难时可恢复至关重要。对于 SQL 数据库备份&#xff0c;有多种可行的方法&#xff0c;对于特定组织来说&#xff0c;方法将取决于其具体需求。 SQL Server 备份的…