【Java并发】【ReentrantLock】适合初学体质的ReentrantLock入门

简介: 前言 什么是ReentrantLock? ReentrantLock 是 Java 并发包 (java.util.concurrent.locks) 中的一个类,它实现了 Lock 接口,提供了与

👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD

🔥 2025本人正在沉淀中... 博客更新速度++

👍 欢迎点赞、收藏、关注,跟上我的更新节奏

📚欢迎订阅专栏,专栏名《在2B工作中寻求并发是否搞错了什么》

前言

马上跟上主播的节奏,看看怎么使用ReentrantLock,这个比较简单,非常适合我们新人朋友奥!

本文只介绍简单的使用,具体原理,主播下一篇具体研究🤗

什么是ReentrantLock?

ReentrantLock 是 Java 并发包 (java.util.concurrent.locks) 中的一个类,它实现了 Lock 接口,提供了与 synchronized 关键字类似的互斥锁功能,但具有更高的灵活性和扩展性。

主要特点

  1. 可重入性

    • synchronized 一样,ReentrantLock 是可重入的。这意味着同一个线程可以多次获取同一个锁,而不会导致死锁。
      • 每次获取锁后,必须相应地进行相同次数的释放。
  2. 公平性

    • ReentrantLock 支持公平锁和非公平锁。公平锁会按照线程请求锁的顺序来分配锁,而非公平锁则允许插队,可能导致某些线程长时间无法获取锁。
      • 通过构造函数可以指定是否使用公平锁,默认是非公平锁。
  3. 可中断的锁获取

    • ReentrantLock 提供了 lockInterruptibly() 方法,允许线程在等待锁的过程中响应中断。
  4. 超时获取锁

    • tryLock() 方法可以尝试获取锁,如果锁不可用,可以选择立即返回或等待一段时间后返回。
  5. 条件变量

    • ReentrantLock 提供了 newCondition() 方法,可以创建 Condition 对象,用于更细粒度的线程通信和等待/通知机制。

ReentrantLock可以怎么用?

基本使用锁

作用: 阻塞等待

  • 非公平锁(默认) :直接尝试通过 CAS(Compare-And-Swap)抢占锁。若失败,则进入等待队列(AQS 队列),自旋或挂起线程。
  • 公平锁:直接进入等待队列,严格按 FIFO 顺序分配锁。
import java.util.concurrent.locks.ReentrantLock;

ReentrantLock lock = new ReentrantLock(); // 默认非公平锁
// ReentrantLock lock = new ReentrantLock(true); // 公平锁

public void doSomething() {
    lock.lock();    // 阻塞直到获取锁
    try {
        // 临界区代码
    } finally {
        lock.unlock(); // 必须手动释放!
    }
}

尝试获取锁

作用: 非阻塞式尝试获取锁,立即返回成功或失败状态,避免线程无限等待。

场景:

  • 需要快速失败逻辑(如资源被占用时执行其他操作)
  • 避免死锁(如同时获取多个锁时)
if (lock.tryLock()) { // 立即尝试,不阻塞
    try { /* 操作 */ } finally { lock.unlock(); }
} else { /* 失败处理 */ }

超时获取锁

作用: 在指定时间内等待获取锁,超时后放弃,避免无限阻塞。

场景:

  • 需要控制最长等待时间(如响应实时性要求高的系统)
  • 避免因死锁导致线程长期挂起
if (lock.tryLock(1, TimeUnit.SECONDS)) { // 最多等待1秒
    try { /* 操作 */ } finally { lock.unlock(); }
} else { /* 超时处理 */ }

可中断获取

作用:等待锁的过程中响应线程中断,避免无法取消的阻塞。

场景:

  • 需要支持任务取消(如用户主动取消长时间操作)
  • 避免线程被永久阻塞
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockInterruptExample {
    public static void main(String[] args) throws InterruptedException {
        ReentrantLock lock = new ReentrantLock();

        // 线程1:先获取锁并执行长时间任务
        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("线程1获取锁,开始执行5秒任务...");
                Thread.sleep(5000); // 模拟长时间任务
                System.out.println("线程1任务完成");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
                System.out.println("线程1释放锁");
            }
        });

        // 线程2:尝试可中断获取锁
        Thread t2 = new Thread(() -> {
            try {
                System.out.println("线程2尝试获取锁(可中断)...");
                lock.lockInterruptibly(); // 可中断获取锁
                try {
                    System.out.println("线程2成功获取锁!");
                } finally {
                    lock.unlock();
                    System.out.println("线程2释放锁");
                }
            } catch (InterruptedException e) {
                System.out.println("线程2在等待锁时被中断!");
            }
        });

        t1.start();
        Thread.sleep(1000); // 确保t1先获取锁
        t2.start();

        Thread.sleep(1000); // 等待t2进入阻塞状态
        t2.interrupt();     // 中断t2的等待
    }
}

条件变量

作用: 通过 Condition 实现线程间的精确协调,替代 Object.wait/notify,支持多个等待队列。

场景:

  • 生产者-消费者模型
  • 线程按条件执行(如任务队列非空时唤醒消费者)
Condition condition = lock.newCondition();

// 线程A:等待条件
lock.lock();
try {
    while (!conditionMet) {
        condition.await(); // 释放锁并等待(类似 wait())
    }
} finally { lock.unlock(); }

// 线程B:通知条件
lock.lock();
try {
    conditionMet = true;
    condition.signal(); // 唤醒一个线程(类似 notify())
    // condition.signalAll(); // 唤醒所有等待线程
} finally { lock.unlock(); }

总结

ReentrantLock优点

  1. 灵活锁控制

    • 支持 tryLock() 非阻塞获取锁。
      • 支持 tryLock(timeout) 超时获取锁。
      • 支持 lockInterruptibly() 可中断获取锁。
  2. 公平性可选

    • 默认是非公平锁(性能更高)。
      • 可通过构造方法选择公平锁(按等待顺序分配锁)。
  3. 多条件变量

    • 通过 newCondition() 创建多个 Condition,实现精细的线程协调(如生产者-消费者模型)。
  4. 可重入性

    • 同一线程可多次获取锁,避免死锁(需匹配相同次数的 unlock())。
  5. 锁状态监控

    • 提供 getHoldCount()isLocked() 等方法,方便调试和监控锁状态。

ReentrantLock缺点

  1. 手动管理锁

    • 必须显式调用 lock()unlock(),遗漏 unlock() 会导致死锁。
  2. 代码复杂性

    • 相比 synchronized,代码更冗长(需配合 try-finally)。
  3. 性能开销

    • 低竞争场景下性能略低于 synchronized(因涉及 API 调用和 JUC 层逻辑)。
  4. 错误使用风险

    • 重入次数不匹配、嵌套锁逻辑复杂等问题易引发 Bug。

适用场景

  1. 需要高级锁功能

    • 超时获取锁(避免死锁)。
      • 可中断锁(支持任务取消)。
      • 尝试获取锁(快速失败)。
  2. 公平锁需求

    • 需按线程请求顺序分配锁(如计费系统、任务调度)。
  3. 复杂线程协调

    • 使用多个 Condition 实现生产者-消费者、任务队列等复杂协作逻辑。
  4. 跨方法锁控制

    • 锁在多个方法中嵌套使用(如递归调用或分布式锁模拟)。
  5. 锁状态监控

    • 需要调试锁竞争情况(如监控等待线程数、锁持有状态)。

后话

什么?这就结束了,不要着急,主播正在快码加鞭的写原理。

小手手,点上关注。

主播马上一起和你们探索ReertrantLock原理😘

目录
相关文章
|
21天前
|
存储 Oracle Java
java零基础学习者入门课程
本课程为Java零基础入门教程,涵盖环境搭建、变量、运算符、条件循环、数组及面向对象基础,每讲配示例代码与实践建议,助你循序渐进掌握核心知识,轻松迈入Java编程世界。
206 0
|
2月前
|
Java
java入门代码示例
本文介绍Java入门基础,包含Hello World、变量类型、条件判断、循环及方法定义等核心语法示例,帮助初学者快速掌握Java编程基本结构与逻辑。
351 0
|
2月前
|
Java API 数据库
2025 年最新 Java 实操学习路线,从入门到高级应用详细指南
2025年Java最新实操学习路线,涵盖从环境搭建到微服务、容器化部署的全流程实战内容,助你掌握Java 21核心特性、Spring Boot 3.2开发、云原生与微服务架构,提升企业级项目开发能力,适合从入门到高级应用的学习需求。
536 0
|
2月前
|
前端开发 Java 数据库连接
帮助新手快速上手的 JAVA 学习路线最详细版涵盖从入门到进阶的 JAVA 学习路线
本Java学习路线涵盖从基础语法、面向对象、异常处理到高级框架、微服务、JVM调优等内容,适合新手入门到进阶,助力掌握企业级开发技能,快速成为合格Java开发者。
443 3
|
2月前
|
监控 Java API
2025 年全新出炉的 Java 学习路线:从入门起步到实操精通的详细指南
2025年Java学习路线与实操指南,涵盖Java 21核心特性、虚拟线程、Spring Boot 3、微服务、Spring Security、容器化部署等前沿技术,助你从入门到企业级开发进阶。
570 0
|
3月前
|
NoSQL Java 关系型数据库
Java 从入门到进阶完整学习路线图规划与实战开发最佳实践指南
本文为Java开发者提供从入门到进阶的完整学习路线图,涵盖基础语法、面向对象、数据结构与算法、并发编程、JVM调优、主流框架(如Spring Boot)、数据库操作(MySQL、Redis)、微服务架构及云原生开发等内容,并结合实战案例与最佳实践,助力高效掌握Java核心技术。
352 1
|
3月前
|
Java 测试技术 API
Java IO流(二):文件操作与NIO入门
本文详解Java NIO与传统IO的区别与优势,涵盖Path、Files类、Channel、Buffer、Selector等核心概念,深入讲解文件操作、目录遍历、NIO实战及性能优化技巧,适合处理大文件与高并发场景,助力高效IO编程与面试准备。
|
3月前
|
Java 编译器 API
Java Lambda表达式与函数式编程入门
Lambda表达式是Java 8引入的重要特性,简化了函数式编程的实现方式。它通过简洁的语法替代传统的匿名内部类,使代码更清晰、易读。本文深入讲解Lambda表达式的基本语法、函数式接口、方法引用等核心概念,并结合集合操作、线程处理、事件回调等实战案例,帮助开发者掌握现代Java编程技巧。同时,还解析了面试中高频出现的相关问题,助你深入理解其原理与应用场景。
|
3月前
|
安全 Java 数据库连接
2025 年最新 Java 学习路线图含实操指南助你高效入门 Java 编程掌握核心技能
2025年最新Java学习路线图,涵盖基础环境搭建、核心特性(如密封类、虚拟线程)、模块化开发、响应式编程、主流框架(Spring Boot 3、Spring Security 6)、数据库操作(JPA + Hibernate 6)及微服务实战,助你掌握企业级开发技能。
484 3
|
3月前
|
算法 Java 测试技术
零基础学 Java: 从语法入门到企业级项目实战的详细学习路线解析
本文为零基础学习者提供完整的Java学习路线,涵盖语法基础、面向对象编程、数据结构与算法、多线程、JVM原理、Spring框架、Spring Boot及项目实战,助你从入门到进阶,系统掌握Java编程技能,提升实战开发能力。
188 0