HelloCoder HelloCoder
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
随笔
关于作者
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
随笔
关于作者
  • 《LearnJavaToFindAJob》

    • 导读

    • 【初级】6~12k档

    • 【中级】12k-26k档

      • JVM进阶

      • Java进阶

        • ConcurrentHashMap面试题
        • CopyOnWriteArrayList的实现原理
        • HashMap的put过程是怎么样的?
        • IO模型有哪些?
        • Synchronized相关
        • ThreadLocal的原理
        • synchronized锁升级
        • valueOf、(String)强转有什么区别?
        • 为什么在lambda中使用的局部变量必须是final或有效final
        • 你知道如何更新缓存吗?如何保证缓存和数据库双写一致性?
        • 八股文之ReentrantLock
        • 分布式事务
        • 可中断和不可中断锁
        • 如何保障生产端消息投递成功?
        • 如何手动触发全量回收垃圾,如何立即触发垃圾回收
        • 数据库连接池为什么要使用ThreadLocal?
        • 线程池中多余的线程是如何回收的
        • 谈谈你对AQS的理解
        • 谈谈你对CAS的理解
        • util.concurrent的理解
        • 高并发下如何保证接口的幂等性?
      • MySQL

      • 中间件

      • 算法

      • 高阶

    • 【高级】26k+档

    • 大厂面试题

    • 求职建议

    • 面经

  • LearnJavaToFindAJob
  • 【中级】12k-26k档
  • Java进阶
#可中断 #不可中断锁
码农阿雨
2026-03-20
目录

可中断和不可中断锁

# 可中断锁与不可中断锁

在 Java 并发编程中,可中断锁与不可中断锁的核心区别在于:线程在获取锁而被阻塞时,是否能够响应外部的中断信号并提前放弃等待。

1. 不可中断锁 当线程因为获取不到锁而进入阻塞状态后,即使其他线程调用了该线程的 interrupt() 方法,它也不会退出阻塞或抛出异常,而是会一直阻塞直到成功获取到锁。不过,中断信号会被保留,待线程获取锁后,可以通过检查中断状态来进行后续处理。

  • 代表实现: synchronized 关键字、ReentrantLock 的 lock() 方法。

2. 可中断锁 当线程因为获取不到锁而阻塞时,它能够响应中断。如果在线程等待锁的过程中被中断,它会立即停止等待,并抛出 InterruptedException 异常。这为开发者提供了一种机制,可以在等待资源超时或被通知取消时,主动释放线程资源,避免线程永久阻塞。

  • 代表实现: ReentrantLock 的 lockInterruptibly() 方法、tryLock(long timeout, TimeUnit unit) 方法。

总结: synchronized 由于是不可中断的,在死锁场景下可能会造成线程无限期阻塞;而 ReentrantLock 提供了可中断的锁获取方式,使得在复杂并发场景下,我们可以更灵活地控制线程的生命周期和资源争抢,提高系统的健壮性。

场景:

“比如在一个批量任务处理系统中,如果用户取消了任务,我们可以通过中断正在等待锁的工作线程,让它立即释放资源并响应取消,而不是一直阻塞在那里占用系统资源。”

# lock() vs lockInterruptibly() 对比

方法 是否可中断 使用场景
lock() 不可中断 确定必须拿到锁的场景
lockInterruptibly() 可中断 任务可取消、有超时控制的场景

# 场景设计

两个线程(t1 和 t2)争抢同一把锁:

  1. t1 先拿到锁,然后持有锁 5 秒钟(模拟长时间业务处理)
  2. t2 尝试获取锁,但因为 t1 持有锁,t2 进入阻塞等待
  3. 主线程在 2 秒后中断 t2
  4. 观察 t2 对中断的响应
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.TimeUnit;

public class LockInterruptiblyExample {
    
    private static final ReentrantLock lock = new ReentrantLock();
    
    public static void main(String[] args) {
        
        // 线程1:先获取锁并长时间持有
        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("线程1: 拿到锁,开始处理业务,将持续5秒");
                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    System.out.println("线程1: 休眠被中断,但锁还在我手里");
                }
                System.out.println("线程1: 业务处理完毕,释放锁");
            } finally {
                lock.unlock();
            }
        }, "线程1");
        
        // 线程2:使用 lockInterruptibly() 获取锁,可以被中断
        Thread t2 = new Thread(() -> {
            try {
                System.out.println("线程2: 尝试通过 lockInterruptibly() 获取锁...");
                // 关键点:这里使用可中断的获取锁方式
                lock.lockInterruptibly();
                
                try {
                    System.out.println("线程2: 成功拿到锁!(这条消息可能看不到,因为会被中断)");
                } finally {
                    lock.unlock();
                    System.out.println("线程2: 释放锁");
                }
                
            } catch (InterruptedException e) {
                System.out.println("线程2: 在等待锁的过程中被中断了!中断异常捕获");
                System.out.println("线程2: 执行清理工作或取消操作...");
                // 这里可以做资源清理、状态恢复等操作
            }
        }, "线程2");
        
        // 启动线程
        t1.start();
        
        // 稍微等待一下,确保线程1先拿到锁
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        t2.start();
        
        // 等待2秒后中断线程2
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("主线程: 尝试中断线程2");
        t2.interrupt();
    }
}

# 运行结果

线程1: 拿到锁,开始处理业务,将持续5秒
线程2: 尝试通过 lockInterruptibly() 获取锁...
主线程: 尝试中断线程2
线程2: 在等待锁的过程中被中断了!中断异常捕获
线程2: 执行清理工作或取消操作...
线程1: 业务处理完毕,释放锁
阅读全文
×

(为防止恶意爬虫)
扫码或搜索:HelloCoder
发送:290992
即可永久解锁本站全部文章

解锁
#可中断#不可中断锁
上次更新: 2026-03-20 10:18:13
最近更新
01
《LeetCode 101》
03-20
02
《LeetCode CookBook》
03-20
03
IDEA、Golang、Pycharm破解安装
03-20
更多文章>
Theme by Vdoing | Copyright © 2020-2026 码农阿雨
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式