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

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

相关推荐
杨杨杨大侠3 分钟前
第8篇:Spring Boot集成 - 开发自己的Starter
java·spring·开源
赵得C27 分钟前
Java 多线程环境下的全局变量缓存实践指南
java·开发语言·后端·spring·缓存
Aeside11 小时前
漫谈代理模式,静态代理到 JDK 和 CGLIB 动态代理
java·设计模式
我梦见我梦见我1 小时前
一文看懂Spring MCP 的请求链路
java·mcp
waynaqua1 小时前
最强工具库 Hutool,使用教程(含 Hutool-AI 使用讲解)
java
渣哥1 小时前
很多人分不清!Java 运行时异常和编译时异常的真正区别
java
weixin_lynhgworld2 小时前
打造绿色生活新方式——旧物二手回收小程序系统开发之路
java·小程序·生活
振鹏Dong2 小时前
Spring事务管理机制深度解析:从JDBC基础到Spring高级实现
java·后端·spring
信码由缰2 小时前
Java包装类:你需要掌握的核心要点
java