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

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

相关推荐
zyl83721几秒前
Java 后端完整技术栈
java·开发语言
想带你从多云到转晴几秒前
04、JAVAEE---多线程进阶、文件I/O、网络初识
java·java-ee
AI人工智能+电脑小能手2 分钟前
【大白话说Java面试题 第107题】【并发篇】第7题:说说 Lock 锁?
java·开发语言·面试
Harvy_没救了5 分钟前
【云计算】华为公有云构建高可用Redis集群
数据库·redis·云计算
霸道流氓气质7 分钟前
RabbitMQ 从零到实战:概念、配置与 Spring Boot 集成指南
spring boot·rabbitmq·java-rabbitmq
夜郎king11 分钟前
SpringBoot 整合 Neo4j 实战:从零搭建经典小说知识图谱完整方案
spring boot·知识图谱·neo4j
Ze3G90nYt13 分钟前
Redis 分布式锁进阶第一百三十一篇
数据库·redis·分布式
杨了个杨898214 分钟前
Dockerfile介绍及镜像制作
java·开发语言
c++之路16 分钟前
CMake 系列教程(三):变量、条件与控制流
java·windows·spring
清晨00119 分钟前
工业互联网实时数据统计一致性保障 — 基于 Redis Lua 的并发安全方案
redis·安全·lua