什么是可中断锁?有什么用?怎么实现?

ReentrantLock可重入、可打断、锁超时实现原理 本文主要从使用到原理讲解了ReentrantLock锁的可重入、可打断和锁超时的特性,希望对大家有帮助。 阅读详情

在 Java 中有两种锁,一种是内置锁 synchronized,一种是显示锁 Lock,其中 Lock 锁是可中断锁,而 synchronized 则为不可中断锁。 ​

所谓的中断锁指的是锁在执行时可被中断,也就是在执行时可以接收 interrupt 的通知,从而中断锁执行。 ​

PS:默认情况下 Lock 也是不可中断锁,但是可以通过特殊的“手段”,可以让其变为可中断锁,接下来我们一起来看。

为什么需要可中断锁?

不可中断锁的问题是,当出现“异常”时,只能一直阻塞等待,别无其他办法,比如下面这个程序。下面的这个程序中有两个线程,其中线程 1 先获取到锁资源执行相应代码,而线程 2 在 0.5s 之后开始尝试获取锁资源,但线程 1 执行时忘记释放锁了,这就造成线程 2 一直阻塞等待的情况,实现代码如下:

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

public class InterruptiblyExample {
    public static void main(String[] args) {
        Lock lock = new ReentrantLock();

        // 创建线程 1
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                System.out.println("线程 1:获取到锁.");
                // 线程 1 未释放锁
            }
        });
        t1.start();

        // 创建线程 2
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                // 先休眠 0.5s,让线程 1 先执行
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 获取锁
                System.out.println("线程 2:等待获取锁.");
                lock.lock();
                try {
                    System.out.println("线程 2:获取锁成功.");
                } finally {
                    lock.unlock();
                }
            }
        });
        t2.start();
    }
}
复制代码

以上代码执行的结果如下:

image.png

从上述结果可以看出,此时线程 2 在等待获取锁的操作,然而经历了 N 久之后...

image.png

再次查看结果,依然是熟悉的画面:

image.png

线程 2 还在阻塞等待获取线程 1 释放锁资源,此时的线程 2 除了等之外,并无其他方法。 ​

并且,但我们熟练的拿出了 JConsole,试图得到一个死锁的具体信息时,却得到了这样的结果:

image.png

并没有检测到任何死锁信息,从上图我们可以看出,当只有一个锁资源的时候,系统并不会把这种情况判定为死锁,当然也没有阻塞等待的具体信息喽,此时只剩下线程 2 孤单地等待着它的“锁儿”。

使用中断锁

然而,中断锁的出现,就可以打破这一僵局,它可以在等待一定时间之后,主动的中断线程 2,以解决线程阻塞等待的问题。 ​

中断锁的核心实现代码是 lock.lockInterruptibly() 方法,它和 lock.lock() 方法作用类似,只不过使用 lockInterruptibly 方法可以优先接收中断的请求,中断锁的具体实现如下:

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

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

        // 创建线程 1
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 加锁操作
                    lock.lock();
                    System.out.println("线程 1:获取到锁.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 线程 1 未释放锁
            }
        });
        t1.start();

        // 创建线程 2
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                // 先休眠 0.5s,让线程 1 先执行
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 获取锁
                try {
                    System.out.println("线程 2:尝试获取锁.");
                    lock.lockInterruptibly(); // 可中断锁
                    System.out.println("线程 2:获取锁成功.");
                } catch (InterruptedException e) {
                    System.out.println("线程 2:执行已被中断.");
                }
            }
        });
        t2.start();

        // 等待 2s 后,终止线程 2
        Thread.sleep(2000);
        if (t2.isAlive()) { // 线程 2 还在执行
            System.out.println("执行线程的中断.");
            t2.interrupt();
        } else {
            System.out.println("线程 2:执行完成.");
        }
    }
}
复制代码

以上代码执行结果如下:

image.png

从上述结果可以看出,当我们使用了 lockInterruptibly 方法就可以在一段时间之后,判断它是否还在阻塞等待,如果结果为真,就可以直接将他中断,如上图效果所示。 ​

但当我们尝试将 lockInterruptibly 方法换成 lock 方法之后(其他代码都不变),执行的结果就完全不一样了,实现代码如下:

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

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

        // 创建线程 1
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 加锁操作
                    lock.lockInterruptibly();
                    System.out.println("线程 1:获取到锁.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 线程 1 未释放锁
            }
        });
        t1.start();

        // 创建线程 2
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                // 先休眠 0.5s,让线程 1 先执行
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 获取锁
                try {
                    System.out.println("线程 2:尝试获取锁.");
                    lock.lock();
                    System.out.println("线程 2:获取锁成功.");
                } catch (Exception e) {
                    System.out.println("线程 2:执行已被中断.");
                }
            }
        });
        t2.start();

        // 等待 2s 后,终止线程 2
        Thread.sleep(2000);
        if (t2.isAlive()) { // 线程 2 还在执行
            System.out.println("执行线程的中断.");
            t2.interrupt();
        } else {
            System.out.println("线程 2:执行完成.");
        }
    }
}
复制代码

以上程序执行结果如下:

image.png

从上图可以看出,当使用 lock 方法时,即使调用了 interrupt 方法依然不能将线程 2 进行中断。

总结

本文介绍了中断锁的实现,通过显示锁 Lock 的 lockInterruptibly 方法来完成,它和 lock 方法作用类似,但 lockInterruptibly 可以优先接收到中断的通知,而 lock 方法只能“死等”锁资源的释放,同时这两个方法的区别也是常见的面试题,希望本文对你有用。 ​


作者:Java中文社群
链接:https://juejin.cn/post/7005545939897172005
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

面试官:什么是可中断锁?有什么用?怎么实现? 在 Java 中有两种锁,一种是内置锁 synchronized,一种是显示锁 Lock,其中 Lock 锁是可中断锁,而 synchronized 则为不可中断锁。 所谓的中断锁指的是锁在执行时可被中断,也就是在执行时可以接收 interrupt 的通知,从而中断锁执行。 ​ PS:默认情况下 Lock 也是不可中断锁,但是可以通过特殊的“手段”,可以让其变为可中断锁,接下来我们一起来看。 为什么需要可中断锁? 不可中断锁的问题是,当出现“异常”时,只能一直阻塞等待,别无其他办法,比如下面这个 阅读详情

相关推荐

Java面试要点86 - Java可重入锁实现ReentrantLock深度剖析

ReentrantLock作为Java并发编程中的重要工具,提供了比synchronized更加灵活和强大的锁机制。通过本文的讲解,我们深入理解了ReentrantLock的基本概念、高级特性以及实际应用场景。在实践中,合理使用ReentrantLock的各种特性,如公平锁、可中断锁和超时机制,可以帮助构建更加健壮和高效的并发应用。也需要注意锁的粒度控制和死锁预防等最佳实践,以确保应用程序的性能和可靠性。

程序媛学姐的博客 598

浅聊一下,可中断锁(ReentrantLock)

今天早上上厕所,上的我痔疮犯了,屁股一坐下去就感觉一根针在刺我,得的是外痔,之前还坚持用痔疮膏来着,但是感觉涂药的那个姿势以及位置我实在无法忍受,就把它给断了,到头来还是屁股糟了罪,

风团团 1402

从零开始的立绘拆包教程

蓝毒小天使天下第一! 本文拆包教程不限于明日方舟,在后面也会给出其他手游的拆包教程,例如少女前线 首先拆包最简单的无非就是拆取游戏资源,例如游戏立绘,音频,视频等,再深层次一点有拆取游戏配置文件,apk反编译得到部分源码 在本文,我们只介绍拆取游戏资源和对游戏资源的后期处理(因为另外两个讲道理我也没太搞懂,虽然可以提取游戏配置文件,但似乎大部分重要的数据都有加密,反编译出来的源码也只是部分,...

Conyrol的博客 9万+

可中断锁

可中断锁:顾名思义,就是可以相应中断的锁。 在Java中,synchronized就不是可中断锁,而Lock是可中断锁。 如果某一线程A正在执行锁中的代码,另一线程B正在等待获取该锁,可能由于等待时间过长,线程B不想等待了,想先处理其他事情,我们可以让它中断自己或者在别的线程中中断它,这种就是可中断锁。 在前面演示lockInterruptibly()的用法时已经体现了Lock的可中断性。 线程在调用lock方法来获得另一个线程所持有的锁的时候,很可能发生阻塞。应该更加谨慎地申请锁。tryLoc..

Leon_Jinhai_Sun的博客 1679

TouchGFX在STM32上的移植全过程:超详细版指南

深入讲解将TouchGFX集成到STM32开发环境的每一步,涵盖配置、驱动适配与UI调试。无论是初学者还是进阶开发者,都能快速掌握TouchGFX在嵌入式平台的应用技巧。

weixin_42443533的博客 602

11种图像清晰度评价函数附MATLAB代码

博主的第一篇博客! 本科毕业论文是“基于图像处理的自动对焦技术研究”,对焦过程中的一个重要阶段是图像清晰度评价,博主自己用MATLAB实现了4类清晰度评价函数:基于图像梯度的清晰度评价函数、频域评价函数、信息熵评价函数、统计学评价函数,总计11种。博主之前没有用过MATLAB,完全是本科论文需要,没办法对着别人的代...

kungfu_rabbit的博客 5万+

ReentrantLock 原理

ReentrantLock是Lock接⼝的默认实现,是⼀种独占锁。相对synchronized⽽⾔,ReentrantLock 提供了更多的操作⽅式以及更细粒度的加锁⽅式。主要特性:1.可重⼊。ReentrantLock是可重⼊锁,因为它会记录之前获得锁线程对象,保存在exclusiveOwenerThread变量中,当⼀个线程要获取锁时,会先判断当前线程是不是已经获取锁的线程。synchronized也是可重⼊锁。12。

qq_63815371的博客 1064

从“要啥”到“咋测”:手把手拆解Aspice SWE.1需求分析,为你的车载/嵌入式项目避坑

本文深入解析Aspice SWE.1需求分析在车载/嵌入式项目中的关键作用,帮助开发者将模糊的系统需求转化为可执行、可验证的软件需求。通过实战案例和结构化方法,详细拆解功能需求原子化、非功能需求工程化表达等核心技巧,为项目避坑提供实用指南。

weixin_31682031的博客 260

悲观锁、乐观锁、自旋锁、偏向锁、轻量/重量级锁、读写锁 共享锁 互斥锁、公平锁非公平锁、可中断锁及其Java实现

首先要打消一种想法,就是一个锁只能属于一种分类。 其实并不是这样,比如一个锁可以同时是悲观锁、可重入锁、公平锁、可中断锁等等。 就像一个人可以是男人、医生、健身爱好者、游戏玩家,这并不矛盾。 国际惯例,上干货。

C_time的博客 618

基于STM32的智能交通灯管理系统设计

本项目基于STM32微控制器设计了一个智能交通灯管理系统,通过多个传感器模块实现对交通灯的智能化控制。项目涉及硬件电路设计、传感器数据采集和逻辑控制实现,适用于城市交通路口或小区路口。该基于STM32的智能交通灯系统通过超声波传感器实现了流量监测,结合LED和蜂鸣器实现了自动交通信号控制,适用于城市或社区路口。基于STM32CubeMX生成的框架,编写红绿灯切换、流量监测和蜂鸣器控制的代码。以下为主循环,通过不断读取传感器数据,结合交通灯和蜂鸣器模块实现智能交通灯控制。

2401_88410555的博客 2063

Python表白代码:“ 星光月夜烟花皆归你,我也归你”(满天烟花盛开、附番外玫瑰)

导语 "慢品人间烟火色 闲观人间岁月长" ———致自己​​​ ​ ???? 遇见我以后,我们的故事就开始了,愿你历经山河,仍觉得人间值得????。 ​ 星光月夜烟花皆归你,我也归你。关于烟花????大家都​知道多少?有多少表白故事情节都发生在烟 花下,想必木木子????不用说大家也知道叭~​​ 今天这则小短文就是关于烟花的故事!你准备好跟我一起进入烟花的世界了嘛? ​正文 “每一句文案,都有一个故事,你仔细听” ​ 1)环境安装???? 准备好:.

顾木子吖的博客 5万+

ReentrantLock实现公平锁,可中断,条件变量,可重入案例

【代码】ReentrantLock实现公平锁,可中断,条件变量,可重入案例。

xuan__xia的博客 395

C-Lodop打印服务系统存在任意文件读取

C-Lodop打印服务系统存在任意文件读取

weixin_43567873的博客 2877

【什么是可中断锁】

本文介绍了中断锁的实现,通过显示锁 Lock 的 lockInterruptibly 方法来完成,它和 lock 方法作用类似,但 lockInterruptibly 可以优先接收到中断的通知,而 lock 方法只能“死等”锁资源的释放,同时这两个方法的区别也是常见的面试题,希望本文对你有用。​。

m0_50116974的博客 1014

基于FFT+BP神经网络/决策树的轴承故障诊断

基于FFT+BP神经网络/决策树的轴承故障诊断

天天酷科研的博客 133

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

【多线程篇08】:详解synchronized锁和ReentrantLock锁

摘要:本文对比了Java中两种可重入锁的实现——synchronized和ReentrantLock,从五个维度分析其差异:1) API层面,synchronized是隐式锁,由JVM管理;ReentrantLock是显式锁,需手动操作。2) 公平性,synchronized仅支持非公平锁,ReentrantLock可配置公平/非公平。3) 中断响应,synchronized不可中断,ReentrantLock支持中断锁获取。4) 功能丰富性,ReentrantLock提供tryLock和Condition

lyh2004_08的博客 869

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

简单实现ReentrantLock,详解ReentrantLock底层原理

AbstractQueuedSynchronizer类不止服务于ReentrantLock类,因此该类里面有很多跟ReentrantLock不想关的代码存在,本文将提取ReentrantLock类和AbstractQueuedSynchronizer类的核心代码进行解释说明。本文末尾将附带经过我提取的手写的ReentrantLock代码,代码上附有我对该锁的理解的注解。的核心就是类,要了解就要先了解一、AbstractQueuedSynchronizer类。

duan614的博客 1897

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Java 可重入锁与synchronized的区别

ReenTrantLock可重入锁(和synchronized的区别)总结 等待可中断:在synchronized中,如果一个线程在等待锁,他只用两种结果,要么获得锁执行完,要么一直保持等待。可中断得等待是通知正在等待的线程,告诉他没必要再等待后。 实现公平锁:公平锁:会按照时间的先后顺序,保证先到先得。特点是它不会产生饥饿现象。而synchroized关键字进行所控制时,锁是非公平的。而重入锁...

颠沛的小丸子 812

Java-Lock超时锁和可中断锁原理

个人理解记录 超时锁的基本原理与独占锁基本相同,不同之处在于“超时”,在调用doAcquireNanos时,首先记录下调用方法的时间,然后尝试获取锁,如过获取成功则直接返回,如果获取失败,判断超时时间是否为0,如果是,则时间超时,返回false,如果不是,则获取当前时间-进入方法的时间,然后在用超时时间-这个结果,得到超时剩余时间,如果剩余超时时间大于1000毫秒,则利用LockSupport挂...

不瘦十斤不换名字 6401

可重入锁,可中断锁,公平锁的理解

线程锁: 1.可重入锁(表明了锁的分配机制): Synchronized和ReentrantLock都是可重入锁 比如当一个线程执行到Synchronized方法method1,而method1方法中调用了另一个Synchrogazed方法method2,此时线程不需要重新申请一把锁,可以直接执行method2 class MyClass { public synchronized

blog:xuchuruo.cn 2297

JAVA锁机制-可重入锁,可中断锁,公平锁,读写锁,自旋锁

如果需要查看具体的synchronized和lock的实现原理,请参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理 在并发编程中,经常遇到多个线程访问同一个 共享资源 ,这时候作为开发者必须考虑如何维护数据一致性,在java中synchronized关键字被常用于维护数据一致性。synchronized机制是给共享资源上锁,只有拿到锁的线程才可以访问共享资源,这样就可以强制使得对共享资源的访问都是顺序的,因为对于共享资源属性访问是必要也是必须的,下文会有具体示例演示。 一

newbei5862的博客 853

synchronized 不可中断详述

【代码】 synchronized 不可中断详述。

weixin_73385730的博客 390

Java 并发之 ReentrantLock 深入分析(与Synchronized区别)

前言 前面两篇文章分析了AQS实现的核心功能,如独占锁、共享锁、可中断锁,条件等待等。而AQS是抽象类,需要子类实现,接下来几篇将重点分析这些子类实现的功能,常见的封装AQS子类的类如下: 注:以上这些类并不是直接继承自AQS,而是内部持有AQS的子类实例,通过AQS的子类实现具体的功能 通过本篇文章,你将了解到: 1、ReentrantLock 实现非公平锁 2、ReentrantLock 实现公平锁 3、ReentrantLock 实现可中断锁 4、ReentrantLock tryLock 原理

877
上一篇: java强制类型转换
下一篇: Synchronized 底层原理总结
java111112313213
博客等级 码龄5年 15粉丝 73原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值