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

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

相关推荐
zym大哥大5 小时前
Redis-List
数据库·redis·缓存
考虑考虑5 小时前
ScopedValue在JDK24以及JDK25的改动
java·后端·java ee
itachi-uchiha5 小时前
关于Tomcat的页面后台管理默认设置
java·tomcat·firefox
骑着bug的coder5 小时前
RestTemplate 和 Feign 传参差异导致的接口调用失败
java
momo_via6 小时前
maven下载与安装及在IDEA中配置maven
java·maven·intellij-idea
Deschen6 小时前
设计模式-适配器模式
java·设计模式·适配器模式
开发游戏的老王6 小时前
虚幻引擎虚拟制片入门教程 之 模型资源的导入
java·游戏引擎·虚幻
编啊编程啊程6 小时前
【004】生菜阅读平台
java·spring boot·spring cloud·dubbo·nio
椎4956 小时前
web后端开发——原理
spring boot·spring·mybatis
Craaaayon6 小时前
【数据结构】二叉树-图解广度优先搜索
java·数据结构·后端·算法·宽度优先