Redisson和可重入锁初认

server/2025/1/15 14:56:50/

文章目录

  • Redisson 简介
    • Redisson 的主要特点
    • Redisson 的核心模块
    • Redisson的优势
    • 使用示例
      • Maven 引入依赖
      • 配置 Redisson 客户端
      • 分布式锁使用示例
    • Redisson 使用场景
      • 总结
  • 可重入锁
    • 关键特性
    • 为什么需要可重入锁
    • 可重入锁的实现方式
    • 可重入锁的实现原理
    • 可重入锁的优缺点
      • 优点
      • 缺点
    • 可重入锁的使用场景
    • 总结

Redisson 简介

  • Redisson 是一个基于 Redis 的 Java 开源框架,旨在为开发者提供简单易用、高效可靠的分布式工具集。它不仅支持常见的 Redis 功能,还封装了大量的分布式结构(如分布式锁、分布式集合、队列等)和高级功能,使得开发者可以在分布式环境中更方便地使用Redis 的能力。
  • Redisson 以 Redis 作为数据存储和通信基础,为分布式系统提供了类似 Java 本地工具的 API,隐藏了底层复杂性,并通过高可靠的机制来确保分布式操作的正确性。

Redisson 的主要特点

  1. 支持多种 Redis 模式:单节点模式、主从模式、哨兵模式、集群模式、云托管服务模式(如 AWS Elasticache、Azure Redis 等)
  2. 分布式工具和数据结构
    • 分布式锁:公平锁、读写锁、可重入锁等。
    • 分布式集合RListRSetRMap 等分布式集合类,封装了 Redis 的数据结构。
    • 分布式队列:支持优先级队列、阻塞队列、延迟队列等。
    • 分布式缓存:支持本地缓存和二级缓存。
  3. 丰富的功能支持
    • 分布式对象:如原子变量(RAtomicLong)、计数器(RCountDownLatch)等。
    • 分布式任务调度:类似 Java ScheduledExecutorService 的分布式任务功能。
    • 事务:提供基于 Redis Lua 脚本的事务支持。
    • 高性能:提供异步和反应式(Reactive)API。
  4. 线程安全:Redisson 所有的分布式工具和数据结构均是线程安全的。
  5. 开发简洁:Redisson 提供了类似 Java 原生 API 的封装,开发起来更加直观和简洁。

Redisson 的核心模块

  1. 分布式锁
    • 可重入锁 (RLock):支持分布式环境下的可重入锁。
    • 公平锁 (RFairLock):保证锁的获取顺序与请求顺序一致。
    • 读写锁 (RReadWriteLock):提供分布式读写锁机制。
    • 信号量 (RSemaphore):类似 Java 的信号量,用于限制并发量。
    • 闭锁 (RCountDownLatch):用于实现分布式闭锁,协调多个线程的启动。
  2. 分布式集合
    • RList:分布式列表,类似 Java 的 List
    • RMap:分布式哈希表,类似 Java 的 HashMap
    • RSet:分布式集合,类似 Java 的 Set
    • RQueue:分布式队列,支持阻塞队列、优先级队列等。
  3. 分布式缓存:支持两级缓存(本地缓存 + Redis 缓存);提供缓存过期和自动清理功能。支持 Spring Cache 接口集成。
  4. 消息队列:支持发布/订阅模式(RTopic)。延迟队列、优先级队列和阻塞队列支持。
  5. 任务调度:提供分布式任务调度功能,类似 Java 的 ScheduledExecutorService。任务调度结果会持久化到 Redis,支持断点续跑。
  6. 异步编程支持:提供异步(CompletableFuture)和反应式(Reactive)API,适合高性能和高并发场景。

Redisson的优势

  1. 封装强大:简化了 Redis 的操作,无需手动处理复杂的 Redis 细节。
  2. 易用性高:API 接口类似于 Java 本地工具,开发成本低。
  3. 高可靠性:实现了分布式锁的可靠机制,防止死锁等问题。
  4. 多功能性:集成了锁、缓存、队列、集合、消息队列等多种功能。
  5. 良好的扩展性:支持各种 Redis 部署模式,适用于单机、集群和云托管环境。

使用示例

Maven 引入依赖

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.42.0</version>
</dependency>

配置 Redisson 客户端

java">import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;public class RedissonConfig {public static RedissonClient createRedissonClient() {// 配置 Redis 连接Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379") // Redis 地址.setPassword(null)                    // Redis 密码(如果有).setDatabase(0);                      // Redis 数据库编号// 创建 Redisson 客户端return Redisson.create(config);}
}

分布式锁使用示例

java">import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;public class RedissonLockExample {public static void main(String[] args) {// 创建 Redisson 客户端RedissonClient redissonClient = RedissonConfig.createRedissonClient();// 获取分布式锁RLock lock = redissonClient.getLock("myLock");try {// 尝试加锁,最多等待 10 秒,锁自动过期时间为 30 秒if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {try {// 加锁成功,执行业务逻辑System.out.println("获取锁成功,执行任务...");Thread.sleep(20000); // 模拟任务耗时 20 秒} finally {// 释放锁lock.unlock();System.out.println("任务完成,释放锁!");}} else {System.out.println("获取锁失败!");}} catch (InterruptedException e) {e.printStackTrace();} finally {// 关闭 Redisson 客户端redissonClient.shutdown();}}
}

输出示例

  • 如果获取锁成功:
    获取锁成功,执行任务...
    任务完成,释放锁!
    
  • 如果锁被其他客户端占用:
    获取锁失败!
    

Redisson 使用场景

  1. 分布式锁:解决多个进程或线程对同一资源的竞争问题。
  2. 分布式队列:用于任务队列、异步任务处理。
  3. 分布式缓存:构建高效的缓存系统,降低数据库压力。
  4. 分布式任务调度:用于定时任务、延迟任务的分布式执行。
  5. 发布/订阅:用于消息推送和事件通知。

总结

  • Redisson 是一个功能全面、易于使用的分布式工具框架,极大地简化了在 Java 应用中使用 Redis 的复杂度。通过 Redisson,可以高效实现分布式锁、缓存、队列等功能,并且无需直接操作底层 Redis 命令,非常适合需要快速开发分布式系统的场景。

可重入锁

  • 可重入锁(Reentrant Lock) 是一种锁机制,允许同一个线程在持有锁的情况下再次获取同一个锁而不会发生死锁。它记录了锁的获取次数,并且只有当线程释放锁的次数与获取锁的次数相等时,锁才会真正被释放。

关键特性

  1. 同一线程可多次获取
    • 如果一个线程已经持有锁,它可以在未释放锁的情况下再次获取锁。
    • 每次获取锁时,锁的计数器会加1。
    • 每次释放锁时,计数器会减1,只有计数器归零时,锁才会真正释放。
  2. 避免死锁
    • 如果没有可重入特性,一个线程在持有锁的情况下再次尝试获取锁会导致自己被锁住(死锁)。
    • 可重入锁通过记录锁的持有线程及其获取次数避免了这种情况。

为什么需要可重入锁

在实际编程中,很多场景中需要调用嵌套的同步代码,例如:

java">public synchronized void methodA() {System.out.println("Method A");methodB(); // 同一个线程再进入另一个同步方法
}public synchronized void methodB() {System.out.println("Method B");
}
  • methodAmethodB 都是同步方法,意味着它们会尝试获取同一个对象锁
  • 如果锁不是可重入的,线程进入 methodA 后,试图在未释放锁的情况下调用 methodB 时会发生死锁。
  • 可重入锁的机制允许线程多次进入同步代码块,从而避免死锁问题。

可重入锁的实现方式

  1. 内置锁(synchronized)
    • Java 的 synchronized 是一种可重入锁。
    • 当一个线程进入 synchronized 方法或代码块后,它可以进入该对象中其他标记为 synchronized 的方法或代码块,而无需再次获取锁。
  • 示例代码:

    java">public class ReentrantLockExample {public synchronized void methodA() {System.out.println(Thread.currentThread().getName() + "进入methodA");methodB();}public synchronized void methodB() {System.out.println(Thread.currentThread().getName() + "进入methodB");}public static void main(String[] args) {ReentrantLockExample example = new ReentrantLockExample();new Thread(example::methodA, "线程1").start();}
    }
    
  • 运行结果:

    线程1进入methodA
    线程1进入methodB
    
  1. 显式锁(ReentrantLock)
    • Java 提供了java.util.concurrent.locks.ReentrantLock,它是一个更加灵活的可重入锁。与synchronized 相比,ReentrantLock 提供了更多功能,比如:尝试获取锁(tryLock)、可中断获取锁(lockInterruptibly)、支持公平锁模式。
    • 示例代码:
    java">import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockExample {private final ReentrantLock lock = new ReentrantLock();public void methodA() {lock.lock();try {System.out.println(Thread.currentThread().getName() + "进入methodA");methodB();} finally {lock.unlock();}}public void methodB() {lock.lock();try {System.out.println(Thread.currentThread().getName() + "进入methodB");} finally {lock.unlock();}}public static void main(String[] args) {ReentrantLockExample example = new ReentrantLockExample();new Thread(example::methodA, "线程1").start();}
    }
    
    • 运行结果:
    线程1进入methodA
    线程1进入methodB
    

可重入锁的实现原理

  1. 内置锁的实现

    • Java 的内置锁(synchronized)由 JVM 实现,底层通过对象头中的标记字段来记录锁的状态。
    • 如果一个线程已经持有锁,它可以再次进入,并在退出时递减计数器,直到计数器为零时释放锁。
  2. ReentrantLock 的实现

    • ReentrantLock 的底层使用 AbstractQueuedSynchronizer(AQS)实现。
    • 核心逻辑
      • 锁记录持有锁的线程 ID 和重入次数(state)。
      • 每次获取锁时,检查当前线程是否已经持有锁,如果是,则增加重入次数。
      • 每次释放锁时,递减计数器,只有计数器为零时才会真正释放锁。

可重入锁的优缺点

优点

  1. 避免死锁:允许同一线程在锁内反复进入,避免了因嵌套调用产生的死锁问题。
  2. 灵活性:使用 ReentrantLock 可以更灵活地尝试获取锁、设置超时、支持公平模式等。
  3. 线程安全:在多线程环境下确保数据一致性。

缺点

  1. 性能开销:由于需要维护锁的状态(比如计数器),可能稍微增加开销。尤其是在轻量级同步场景下,相比无锁机制稍慢。
  2. 复杂性:显式锁(如 ReentrantLock)需要显式释放锁,容易因代码逻辑问题导致忘记释放锁,从而引发死锁。

可重入锁的使用场景

  1. 嵌套同步代码块:当线程需要多次进入同一个锁时,避免死锁。
  2. 分布式系统中实现分布式锁:例如Redisson 提供的分布式锁就支持可重入功能。
  3. 需要灵活的锁控制:如果需要控制超时时间、可中断锁获取等功能,可以使用显式的 ReentrantLock

总结

可重入锁是一种解决嵌套同步问题的重要机制,广泛应用于多线程编程中。在 Java 中,synchronizedReentrantLock 都是可重入锁。根据实际需求选择使用内置锁或显式锁,可以在保证线程安全的同时兼顾性能和开发效率。


http://www.ppmy.cn/server/158583.html

相关文章

【Python】使用python 对excel文件进行加密

最近在跟同事对接工作的时候&#xff0c;我需要把Excel文件发给对方。 但是由于文件内容的私密性&#xff0c;需要对Excel文件进行加密&#xff0c;保护文件以免给第三方看到&#xff0c;保障数据的安全。 在Python中&#xff0c;有多种方法可以对Excel文件进行加密。以下是几…

好用的php商城源码有哪些?

选择一个优秀的商城工具&#xff0c;能更好地帮助大家建立一个好用的商城系统。目前比较流行的都是开源PHP商城系统&#xff0c;那么现实中都有哪些好用的PHP商城源码值得推荐呢&#xff1f;下面就带大家一起来了解一下。 1.TigShop 【推荐指数】&#xff1a;★★★★★☆ 【推…

day08_Kafka

文章目录 day08_Kafka课程笔记一、今日课程内容一、消息队列&#xff08;了解&#xff09;**为什么消息队列就像是“数据的快递员”&#xff1f;****实际意义**1、产生背景2、消息队列介绍2.1 常见的消息队列产品2.2 应用场景2.3 消息队列中两种消息模型 二、Kafka的基本介绍1、…

springboot基于安卓的反诈APP

Spring Boot基于安卓的反诈APP是一个结合了Spring Boot后端技术和安卓前端技术的反诈骗应用程序&#xff0c;旨在为用户提供全面、高效的反诈防护服务。 一、技术架构 后端&#xff1a;采用Spring Boot框架&#xff0c;利用其自动配置、简化依赖管理等功能&#xff0c;构建…

Open FPV VTX开源之第一次出图

Open FPV VTX开源之第一次出图 1. 源由2. 连线2.1 飞控2.2 调试 3. serial3.1 启动log - uboot3.2 登录版本 - linux3.3 获取有线IP 4. ssh - linux5. PixelPilot出图6. 总结7. 参考资料8. 补充8.1 8812AU网卡8.2 DEBUG串口部分乱码8.3 偶尔启动卡住8.4 花屏、丢包严重 1. 源由…

CSS3 弹性盒子

CSS3 弹性盒子 介绍 CSS3 弹性盒子&#xff08;Flexbox&#xff09;是一种用于布局设计的强大工具。它提供了一种更加高效的方式来对容器内的子元素进行排列、对齐和分配空间。Flexbox 的设计目标是提供一种统一的布局模型&#xff0c;能够适应不同屏幕尺寸和设备类型&#x…

【自然语言处理】P1 自然语言处理概述

目录 什么是自然语言处理定义常用术语自然语言处理的任务自然语言处理的发展历程自然语言处理的挑战自然语言处理的常用技术TF-IDF词嵌入分词循环神经网络注意力机制预训练 什么是自然语言处理 定义 自然语言指的是人类的语言&#xff0c;如中文、英语等&#xff0c;处理特指…

[Unity] 【图形渲染】Unity Shader光照基础2-标准光照模型

在早期的游戏开发中,游戏引擎大多使用标准光照模型来模拟光线如何与物体表面交互。虽然现代引擎通常会采用更复杂的光照技术,但标准光照模型依然是一个关键概念,特别是在实时渲染中。在本文中,我们将深入探讨Unity标准光照模型的各个组成部分,了解光线如何与物体表面相互作…