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 是分布式系统中控制并发的利器,但一定要合理设计超时机制,避免死锁和性能问题! 🚀

相关推荐
编程乐学(Arfan开发工程师)2 分钟前
42、响应处理-【源码分析】-浏览器与PostMan内容协商完全适配
java·spring boot·后端·测试工具·lua·postman
汪子熙6 分钟前
深入解析互斥锁(Mutex):并发编程中的关键同步机制
后端·面试
Livingbody6 分钟前
mac系统下永久设置环境变量之【huggingface更换镜像站】
后端
Livingbody7 分钟前
Transformers Pipeline 文本情感分类
后端
珹洺7 分钟前
数据库系统概论(十七)超详细讲解数据库规范化与五大范式(从函数依赖到多值依赖,再到五大范式,附带例题,表格,知识图谱对比带你一步步掌握)
java·数据库·sql·安全·oracle
坚持学习永不言弃8 分钟前
单例模式
后端
用户79117724235839 分钟前
黑马点评【基于redis实现共享session登录】
java·redis
coding随想9 分钟前
数据结构界的‘直男’——线性结构的全方位解析
后端
十字路口的火丁10 分钟前
gin + endless 实现服务平滑重启
后端
网安INF12 分钟前
CVE-2023-25194源码分析与漏洞复现(Kafka JNDI注入)
java·web安全·网络安全·kafka·漏洞·jndi注入