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

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

相关推荐
皮皮林5515 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
卡尔特斯9 小时前
Android Kotlin 项目代理配置【详细步骤(可选)】
android·java·kotlin
白鲸开源9 小时前
Ubuntu 22 下 DolphinScheduler 3.x 伪集群部署实录
java·ubuntu·开源
ytadpole9 小时前
Java 25 新特性 更简洁、更高效、更现代
java·后端
纪莫10 小时前
A公司一面:类加载的过程是怎么样的? 双亲委派的优点和缺点? 产生fullGC的情况有哪些? spring的动态代理有哪些?区别是什么? 如何排查CPU使用率过高?
java·java面试⑧股
JavaGuide10 小时前
JDK 25(长期支持版) 发布,新特性解读!
java·后端
用户37215742613510 小时前
Java 轻松批量替换 Word 文档文字内容
java
白鲸开源10 小时前
教你数分钟内创建并运行一个 DolphinScheduler Workflow!
java
Java中文社群11 小时前
有点意思!Java8后最有用新特性排行榜!
java·后端·面试
代码匠心11 小时前
从零开始学Flink:数据源
java·大数据·后端·flink