导读:本期聚焦于小伙伴创作的《如何在 Java 中通过 ReentrantLock.lockInterruptibly() 实现支持被外部中断的阻塞式加锁》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何在 Java 中通过 ReentrantLock.lockInterruptibly() 实现支持被外部中断的阻塞式加锁》有用,将其分享出去将是对创作者最好的鼓励。

在Java并发编程中,ReentrantLock是常用的线程同步工具,它提供了比synchronized更灵活的锁操作能力。其中lockInterruptibly方法允许线程在等待获取锁的过程中响应中断,解决了普通lock方法无法被中断的问题,适合需要支持取消等待锁的场景。

lockInterruptibly 方法的基本特性

ReentrantLock的lockInterruptibly方法是Lock接口定义的方法,它的核心特点是:当线程调用该方法尝试获取锁时,如果锁被其他线程持有,当前线程会进入阻塞状态等待锁,但在这个过程中如果其他线程对该线程发起了中断请求,等待中的线程会立即抛出InterruptedException并停止等待,而不是一直阻塞下去。

和普通的lock方法相比,两者的差异如下:

方法等待锁时是否响应中断获取不到锁时的行为
lock()不响应一直阻塞直到获取到锁
lockInterruptibly()响应阻塞等待,收到中断则抛出异常终止等待

基础使用示例

下面是一个简单的示例,演示两个线程竞争同一把锁,其中一个线程在等待锁的过程中被中断的场景:

import java.util.concurrent.locks.ReentrantLock;

public class LockInterruptiblyDemo {
    // 创建可重入锁实例
    private static final ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        // 线程1先获取锁,持有锁一段时间
        Thread thread1 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("线程1获取到锁,开始执行任务");
                // 模拟任务执行,持有锁3秒
                Thread.sleep(3000);
                System.out.println("线程1任务执行完成,释放锁");
            } catch (InterruptedException e) {
                System.out.println("线程1被中断");
            } finally {
                lock.unlock();
            }
        }, "thread-1");

        // 线程2尝试用lockInterruptibly获取锁
        Thread thread2 = new Thread(() -> {
            try {
                System.out.println("线程2尝试获取锁,等待中...");
                // 支持中断的加锁方式
                lock.lockInterruptibly();
                try {
                    System.out.println("线程2成功获取到锁,执行任务");
                } finally {
                    lock.unlock();
                }
            } catch (InterruptedException e) {
                System.out.println("线程2在等待锁的过程中被中断,停止等待");
            }
        }, "thread-2");

        // 启动线程
        thread1.start();
        // 确保线程1先获取到锁
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread2.start();

        // 等待1秒后中断线程2
        try {
            Thread.sleep(1000);
            System.out.println("主线程中断线程2");
            thread2.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行上述代码,输出结果大致如下:

线程1获取到锁,开始执行任务
线程2尝试获取锁,等待中...
主线程中断线程2
线程2在等待锁的过程中被中断,停止等待
线程1任务执行完成,释放锁

可以看到线程2在等待锁的过程中被中断后,立刻抛出了InterruptedException,没有继续等待线程1释放锁。

实际开发中的注意事项

  • 调用lockInterruptibly方法后,一定要在try块外部捕获InterruptedException,或者在方法签名上声明抛出该异常,否则代码会编译报错。
  • 获取锁成功后,一定要在finally块中释放锁,避免因为异常导致锁无法释放,引发死锁问题。
  • 如果线程的中断状态已经被设置,再调用lockInterruptibly方法会立刻抛出InterruptedException,不会尝试获取锁。
  • lockInterruptibly方法适合用在需要支持任务取消、超时等待等场景,比如线程池中的可取消任务、限时的资源获取逻辑等。

超时加锁结合中断的场景

ReentrantLock还提供了tryLock(long timeout, TimeUnit unit)方法,该方法同样支持中断,并且可以设置等待锁的超时时间,结合lockInterruptibly可以实现更灵活的加锁逻辑:

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class TryLockInterruptDemo {
    private static final ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread taskThread = new Thread(() -> {
            try {
                // 尝试在2秒内获取锁,同时支持中断
                if (lock.tryLock(2, TimeUnit.SECONDS)) {
                    try {
                        System.out.println("任务线程获取到锁,执行任务");
                        Thread.sleep(3000);
                    } finally {
                        lock.unlock();
                    }
                } else {
                    System.out.println("等待锁超时,未获取到锁");
                }
            } catch (InterruptedException e) {
                System.out.println("任务线程在等待锁时被中断");
            }
        });

        lock.lock();
        try {
            System.out.println("主线程获取锁,启动任务线程");
            taskThread.start();
            // 等待1秒后中断任务线程
            Thread.sleep(1000);
            taskThread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

该示例中任务线程设置2秒的锁等待超时,同时在等待1秒时被中断,会立刻触发中断异常,不会继续等待剩余的1秒时间。

总结

ReentrantLock的lockInterruptibly方法为Java多线程加锁提供了中断响应能力,解决了普通加锁方式无法取消等待的问题。在实际开发中,需要根据场景选择合适的加锁方法:如果不需要支持中断,使用lock方法即可;如果需要允许线程在等待锁时可以被取消,优先使用lockInterruptibly或者带超时的tryLock方法。正确使用该特性可以提升多线程程序的健壮性,避免无意义的线程阻塞。

ReentrantLocklockInterruptiblyJava阻塞式加锁线程中断修改时间:2026-06-28 23:24:45

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。