Java并发编程之ReentrantLock的实现示例

 更新时间:2026年02月13日 09:22:05   作者:Johnny Lnex  
本文主要介绍了Java并发编程之ReentrantLock的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、可中断锁

1. 核心方法:lockInterruptibly()

  • 作用:允许线程在等待锁的过程中响应中断请求。
  • 适用场景:需要支持任务取消或中断的同步操作(如用户手动取消长时间等待的任务)。

2. 代码示例

ReentrantLock lock = new ReentrantLock();

Thread thread = new Thread(() -> {
    try {
        lock.lockInterruptibly(); // 可中断获取锁
        try {
            System.out.println("线程获取锁并执行任务");
            Thread.sleep(5000); // 模拟耗时操作
        } finally {
            lock.unlock();
        }
    } catch (InterruptedException e) {
        System.out.println("线程被中断,放弃获取锁");
    }
});

lock.lock(); // 主线程先获取锁
try {
    thread.start();
    Thread.sleep(1000); // 确保子线程开始等待锁
    thread.interrupt(); // 中断子线程
} finally {
    lock.unlock();
}

3. 行为分析

  • 未中断时:线程正常获取锁并执行任务。
  • 中断时:抛出 InterruptedException,线程退出等待队列。

二、锁超时

1. 核心方法:tryLock()

  • 无参方法boolean tryLock()
    立即尝试获取锁,成功返回 true,失败返回 false

  • 带超时方法boolean tryLock(long timeout, TimeUnit unit)
    在指定时间内尝试获取锁,超时后放弃。

2. 代码示例:避免死锁

ReentrantLock lockA = new ReentrantLock();
ReentrantLock lockB = new ReentrantLock();

Thread thread1 = new Thread(() -> {
    try {
        if (lockA.tryLock(1, TimeUnit.SECONDS)) { // 尝试获取lockA
            try {
                if (lockB.tryLock(1, TimeUnit.SECONDS)) { // 尝试获取lockB
                    System.out.println("Thread1完成任务");
                }
            } finally {
                if (lockB.isHeldByCurrentThread()) lockB.unlock();
            }
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        if (lockA.isHeldByCurrentThread()) lockA.unlock();
    }
});

Thread thread2 = new Thread(() -> { /* 类似逻辑,先尝试lockB再lockA */ });
thread1.start();
thread2.start();

3. 应用场景

  • 死锁预防:通过超时放弃锁请求,打破循环等待。
  • 响应性优化:避免线程长时间阻塞影响系统响应速度。

三、条件变量

1. 核心机制

  • 创建条件变量Condition condition = lock.newCondition();
  • 等待条件condition.await();
  • 唤醒线程condition.signal()condition.signalAll()

2. 代码示例:生产者-消费者模型

ReentrantLock lock = new ReentrantLock();
Condition notEmpty = lock.newCondition(); // 非空条件
Condition notFull = lock.newCondition();  // 非满条件
Queue<Integer> queue = new LinkedList<>();
int maxSize = 10;

// 生产者
new Thread(() -> {
    lock.lock();
    try {
        while (queue.size() == maxSize) {
            notFull.await(); // 等待队列非满
        }
        queue.add(1);
        notEmpty.signal(); // 通知消费者
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}).start();

// 消费者
new Thread(() -> {
    lock.lock();
    try {
        while (queue.isEmpty()) {
            notEmpty.await(); // 等待队列非空
        }
        queue.poll();
        notFull.signal(); // 通知生产者
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}).start();

3. 优势对比wait()/notify()

特性Conditionwait()/notify()
多条件支持✅ 可创建多个条件变量❌ 每个对象仅一个等待队列
精准唤醒✅ signal() 唤醒指定条件队列的线程❌ notify() 随机唤醒

四、关键注意事项

1. 锁释放

  • 必须手动释放:lock.unlock() 需放在 finally 块中确保执行。
  • 重入次数匹配:加锁和解锁次数必须一致,否则导致锁无法释放。

2. 中断处理

  • 响应中断:lockInterruptibly() 和 await() 需捕获 InterruptedException。
  • 恢复中断状态:调用 Thread.currentThread().interrupt() 保留中断标志。

到此这篇关于Java并发编程之ReentrantLock的实现示例的文章就介绍到这了,更多相关Java ReentrantLock内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • idea创建xml文件全过程

    idea创建xml文件全过程

    总结:通过File->Settings->Editor->FileAndCodeTemplates,创建一个自定义的XML文件模板,并命名为XMLFile.xml,后缀名为xml,模板内容可自定义,并启用实时模板功能,然后在文件夹中右键New,即可找到并创建XML文件
    2025-11-11
  • Spring Data JPA 之 JpaRepository的使用

    Spring Data JPA 之 JpaRepository的使用

    这篇文章主要介绍了Spring Data JPA 之 JpaRepository的使用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • 使用Java和PostgreSQL存储向量数据的实现指南

    使用Java和PostgreSQL存储向量数据的实现指南

    在当今的数字化时代,数据存储的方式和技术正变得越来越复杂和多样化,随着机器学习和数据科学的发展,向量数据的存储和管理变得尤为重要,本文将详细介绍如何使用 Java 和 PostgreSQL 数据库来存储向量数据,需要的朋友可以参考下
    2024-09-09
  • 如何在springboot项目中自定义404页面

    如何在springboot项目中自定义404页面

    今天点击菜单的时候不小心点开了一个不存在的页面,然后看到浏览器给的一个默认的404页面,这篇文章主要介绍了如何在springboot项目中自定义404页面,需要的朋友可以参考下
    2024-05-05
  • JVM代码运行逻辑解读

    JVM代码运行逻辑解读

    这篇文章主要介绍了JVM代码运行逻辑,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • Java如何自定义类数组的创建和初始化

    Java如何自定义类数组的创建和初始化

    这篇文章主要介绍了Java如何自定义类数组的创建和初始化,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • IntelliJ IDEA(2017)安装和破解的方法

    IntelliJ IDEA(2017)安装和破解的方法

    这篇文章主要介绍了IntelliJ IDEA(2017)安装和破解的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • MyBatis 关联查询延迟加载实战案例

    MyBatis 关联查询延迟加载实战案例

    本文介绍了MyBatis开发中一对多、一对一关联查询的配置方法,重点讲解了resultMap、association、collection等核心标签的使用场景和用语法,并详细解释了延迟加载(fetchType属性)的配置方法和执行流程,最后总结了单表查询、一对一关联和一对多关联的配置方法和注意事项
    2026-05-05
  • Java如何把数组转换为ArrayList

    Java如何把数组转换为ArrayList

    这篇文章主要介绍了Java如何把数组转换为ArrayList,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • JVM入门之JVM内存结构内容详解

    JVM入门之JVM内存结构内容详解

    这篇文章主要介绍了JVM入门之JVM内存结构内容详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09

最新评论