RLock类详细介绍、应用场景和示例代码

概述

org.redisson.api.RLock 是 Redisson 提供的 分布式可重入锁 (类似 ReentrantLock),基于 Redis 实现,常用于 分布式环境 下的 并发控制


1. RLock 详解

🔹 特点

  • 基于 Redis 实现 ,支持 集群环境
  • 可重入,同一个线程可以多次获取同一把锁,不会被阻塞。
  • 支持 WatchDog 机制,避免锁因宕机未手动释放而导致死锁。
  • 支持超时自动释放,避免死锁问题。
  • 支持公平锁、联锁、红锁等多种高级特性

🔹 依赖

XML 复制代码
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.22.1</version>
</dependency>

🔹 获取 RLock

java 复制代码
RedissonClient redissonClient = Redisson.create(); // 需要传入 Redis 配置
RLock lock = redissonClient.getLock("myLock");

2. RLock 常用方法

方法 说明
lock() 阻塞式加锁(默认 WatchDog 续期)
lock(long leaseTime, TimeUnit unit) 加锁 + 设定过期时间,到期自动释放
tryLock() 非阻塞式 ,如果获取不到锁立即返回 false
tryLock(long waitTime, long leaseTime, TimeUnit unit) 尝试获取锁 ,最长等待 waitTime,成功后 leaseTime 过期自动释放
unlock() 释放锁
isLocked() 判断锁是否被任意线程占用
isHeldByCurrentThread() 判断当前线程是否持有锁
forceUnlock() 强制释放锁,无论是谁持有锁

3. RLock 典型应用场景

1. 解决分布式环境下的并发问题

多个服务实例(如 AB)同时访问共享资源时,防止并发冲突。

场景:多个线程同时对某个商品库存进行扣减操作,需要防止超卖。

java 复制代码
public void reduceStock() {
    RLock lock = redissonClient.getLock("product_stock_lock");
    try {
        lock.lock();  // 加锁(默认30s自动续期)
        int stock = getStock();
        if (stock > 0) {
            updateStock(stock - 1);
        }
    } finally {
        lock.unlock(); // 释放锁
    }
}

⚠ 注意 :如果 lock.lock() 后方法抛异常,未执行 unlock(),Redisson 默认使用 WatchDog 机制自动续期,不会发生死锁。


2. 限制用户重复提交

场景:用户短时间内重复提交订单,导致重复下单。

java 复制代码
public String submitOrder(String userId) {
    RLock lock = redissonClient.getLock("order_lock:" + userId);
    boolean success = lock.tryLock();
    if (!success) {
        return "请勿重复提交";
    }
    try {
        processOrder();
        return "订单提交成功";
    } finally {
        lock.unlock();
    }
}

3. 分布式定时任务的幂等控制

场景:多个定时任务实例同时启动,保证同一时间只有一个任务执行。

java 复制代码
public void executeTask() {
    RLock lock = redissonClient.getLock("task_lock");
    if (!lock.tryLock()) {
        return; // 其他实例已持有锁,当前实例不执行任务
    }
    try {
        performTask();
    } finally {
        lock.unlock();
    }
}

4. 秒杀场景:高并发库存扣减

场景:多用户高并发秒杀商品,避免超卖。

java 复制代码
public boolean secKill(String productId) {
    RLock lock = redissonClient.getLock("sec_kill_lock:" + productId);
    try {
        if (lock.tryLock(100, 10, TimeUnit.MILLISECONDS)) {
            int stock = getStock(productId);
            if (stock > 0) {
                updateStock(productId, stock - 1);
                return true;
            }
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
    return false;
}

🔹 关键点

  • tryLock(100, 10, TimeUnit.MILLISECONDS)
    • 等待最长 100ms 获取锁
    • 持有锁 10ms 后自动释放
  • 适用于高并发业务,防止 Redis 长时间占用锁资源。

5. 订单支付超时取消

场景:订单创建 30 分钟未支付,自动取消订单。

java 复制代码
public void setOrderExpire(String orderId) {
    RLock lock = redissonClient.getLock("order_expire_lock:" + orderId);
    lock.lock(30, TimeUnit.MINUTES); // 30 分钟后自动释放锁
}

4. RLock 可能存在的问题

问题 解决方案
锁未释放(死锁) 1️⃣ lock.lock(leaseTime, TimeUnit.SECONDS) 设置超时 2️⃣ 使用 WatchDog 机制
Redis 宕机,锁丢失 采用 Redis 主从 + 哨兵 ,或者使用 Redisson RedLock
线程异常退出,锁未释放 1️⃣ try-finally 释放锁 2️⃣ lock.lock(leaseTime, TimeUnit.SECONDS) 设定过期时间
多个服务实例并发竞争锁 使用 tryLock(waitTime, leaseTime, TimeUnit.SECONDS)

5. 进阶:Redisson 其他锁

锁类型 说明
RLock 可重入锁
RReadWriteLock 读写锁,读读共享,写独占
RFairLock 公平锁,先请求的先获得锁
RMultiLock 联锁 ,多个 RLock 绑定在一起
RedLock 红锁 ,适用于 Redis 主从集群
RSemaphore 信号量 ,类似 Java Semaphore
RCountDownLatch 分布式 CountDownLatch

示例:读写锁

java 复制代码
RReadWriteLock rwLock = redissonClient.getReadWriteLock("my_rw_lock");
rwLock.readLock().lock();
try {
    System.out.println("执行读操作...");
} finally {
    rwLock.readLock().unlock();
}

6. 总结

RLock 是基于 Redis 实现的分布式锁,适用于高并发环境

支持可重入、超时释放、WatchDog 续期

适用于库存扣减、订单防重、定时任务、秒杀等场景

如果需要更高可靠性,可使用 RedLock

🔥 RLock 是分布式系统中控制并发的利器,但一定要合理设计超时机制,避免死锁和性能问题! 🚀

相关推荐
枣伊吕波10 分钟前
第六节第二部分:抽象类的应用-模板方法设计模式
android·java·设计模式
xinxiyinhe13 分钟前
内存泄漏与OOM崩溃根治方案:JVM与原生内存池差异化排查手册
java·开发语言·jvm
心向阳光的天域17 分钟前
黑马Java跟学.最新AI+若依框架项目开发(一)
java
what_201822 分钟前
分布式链路跟踪
java·运维·分布式
oliveira-time30 分钟前
ArrayList和LinkedList区别
java·开发语言
潮流coder33 分钟前
IntelliJ IDEA给Controller、Service、Mapper不同文件设置不同的文件头注释模板、Velocity模板引擎
java·ide·intellij-idea
码农飞哥40 分钟前
互联网大厂Java求职面试实战:Spring Boot与微服务场景深度解析
java·数据库·spring boot·安全·微服务·消息队列·互联网医疗
Akiiiira1 小时前
【日撸 Java 300行】Day 14(栈)
java·开发语言
猴子请来的逗比4891 小时前
tomcat与nginx之间实现多级代理
java·nginx·tomcat
一丝晨光1 小时前
数值溢出保护?数值溢出应该是多少?Swift如何让整数计算溢出不抛出异常?类型最大值和最小值?
java·javascript·c++·rust·go·c·swift