springboot如何redis锁

如何解决超卖问题?

超卖问题:就是多个线程并发执行,目前唯一方案是加锁。

如图:悲观锁其实还有数据库的互斥锁。悲观锁是最常见的

乐观锁实现的原理:

版本号:

这种方案就是:扣款库存的时候首先先查询版本号,然后再修改库存的时候把查询的库存号当做条件并把版本号进行+1,库存-1。

CAS发

和第一种一样只是把版本号换成库存了。很好理解

优点:性能比悲观锁好。

缺点:高并发情况下依然存在超卖的问题。

乐观锁的如何使用:

如图上面是支付宝回调出现的扣减库存的。这里的扣减库存。

sysProductMapper.deductionOfInventory(sysProduct.getCode());

这个就是乐观锁的一种实现方案:

在不添加版本号的前提下还有一种就是

可以这也理解我举一个例子

有的人会提出这个疑问。mysql的隔离级别是读已提交。但是update会进行获取写如果code不是索引则会全表锁,如果是索引会行锁这样下来就不会出现那种情况了。事务A拿到后会对这条数据进行行锁的。

悲观锁:直接可以加上synchronized在方法上,不过关键字加载方法上代表是当前这个对象进行锁

性能过低

当前也可以这样。因为是在同一个code加锁,所以我的锁是库存编码

还有一点一定要注意,如果你的锁对象是string那无所谓常量池是同一个。

但是如果你是Long类型转换为toString就不一样了看下源码

这是Long类型转换为toString的源码

java 复制代码
    /**
     * Returns a {@code String} object representing this
     * {@code Long}'s value.  The value is converted to signed
     * decimal representation and returned as a string, exactly as if
     * the {@code long} value were given as an argument to the
     * {@link java.lang.Long#toString(long)} method.
     *
     * @return  a string representation of the value of this object in
     *          base 10.
     */
    public String toString() {
        return toString(value);
    }

    /**
     * Returns a {@code String} object representing the specified
     * {@code long}.  The argument is converted to signed decimal
     * representation and returned as a string, exactly as if the
     * argument and the radix 10 were given as arguments to the {@link
     * #toString(long, int)} method.
     *
     * @param   i   a {@code long} to be converted.
     * @return  a string representation of the argument in base 10.
     */
    public static String toString(long i) {
        if (i == Long.MIN_VALUE)
            return "-9223372036854775808";
        int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
        char[] buf = new char[size];
        getChars(i, size, buf);
        return new String(buf, true);
    }

看到toString了吗?他会进行一直new所以尽可能是看着是同一个对象,但是锁的值不同。

java 复制代码
    Long a = 2L;
        String s1 = a.toString(); // String@123
        String s2 = s1.intern();  // 常量池中的"2"(引用为String@789)

        Long b = 2L;
        String s3 = b.toString(); // String@456
        String s4 = s3.intern();  // 同样返回常量池中的"2"(String@789)

所以如果是转换为string类型一定要进行intern

一般并发量特别大的情况下一般别进行锁表

相关推荐
咩咩啃树皮9 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
鱟鲥鳚10 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
大模型码小白11 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司12 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地13 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun31415913 小时前
TCP超时重传机制是为了解决什么问题?
java
二宝哥14 小时前
CentOS 7.9 系统下 Redis 5.0.4 单机安装与源码编译安装指南
redis·centos
莫逸风15 小时前
【AgentScope 2.0】 0. 学习指南
java·llm·agent·agentscope
隔窗听雨眠15 小时前
Spring Boot在云原生时代的编程范式革新研究
spring boot·后端·云原生
z1234567898616 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程