「Juc并发编程」什么是可重入锁?

article/2025/10/14 0:23:45

「Juc并发编程」什么是可重入锁?

文章目录

  • 「Juc并发编程」什么是可重入锁?
    • 一、概述
    • 二、解释
    • 三、可重入锁种类
      • 隐式锁
        • 同步块
        • 同步方法
      • 显式锁
    • 四、Synchronized的重入的实现机理

一、概述

可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一个对象或者class),不会因为之前已经获取过还没释放而阻塞。

Java中ReentrantLocksynchronized都是可重入锁,可重入锁的一个优点是可一定程度避免死锁


二、解释

可:可以。
重:再次。
入:进入。
锁:同步锁。进入什么:进入同步域(即同步代码块/方法或显式锁锁定的代码)
一句话:一个线程中的多个流程可以获取同一把锁,持有这把同步锁可以再次进入。
自己可以获取自己的内部锁

三、可重入锁种类

隐式锁

(即synchronized关键字使用的锁)默认是可重入锁

指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁,这样的锁就叫做可重入锁。
简单的来说就是:在一个synchronized修饰的方法或代码块的内部调用本类的其他synchronized修饰的方法或代码块时,是永远可以得到锁的与可重入锁相反,不可重入锁不可递归调用,递归调用就发生死锁。

同步块

public class ReEntryLockDemo{public static void main(String[] args){final Object objectLockA = new Object();new Thread(() -> {synchronized (objectLockA){System.out.println("-----外层调用");synchronized (objectLockA){System.out.println("-----中层调用");synchronized (objectLockA){System.out.println("-----内层调用");}}}},"t1").start();}
}

运行结果

image-20230222022653239

结论

在外部调用中,已经锁住了Object类,而中层调用和内层调用仍可以获取到锁,因此synchronized是可重入锁。简单来说就是:在一个synchronized修饰的方法或代码块的内部调用本类的其他synchronized修饰的方法或代码块时,是永远可以得到锁的。

同步方法

public class ReEntryLockDemo{public synchronized void m1(){System.out.println(Thread.currentThread().getName()+"\t-----come in");m2();}public synchronized void m2(){System.out.println(Thread.currentThread().getName()+"\t-----come in");m3();}public synchronized void m3(){System.out.println(Thread.currentThread().getName()+"\t-----come in");}public static void main(String[] args){ReEntryLockDemo reEntryLockDemo = new ReEntryLockDemo();reEntryLockDemo.m1();}
}

运行结果

image-20230222022644105

结论

理论上三个方法应该是有三个不同的线程进行操作,而这里从头到尾都是t1线程进来,由此可知这是一个可重入锁。

显式锁

(即Lock)也有ReentrantLock这样的可重入锁。

/*** 在一个Synchronized修饰的方法或代码块的内部调用本类的其他Synchronized修饰的方法或代码块时,是永远可以得到锁的*/
public class ReEntryLockDemo{static Lock lock = new ReentrantLock();public static void main(String[] args){new Thread(() -> {lock.lock();try{System.out.println("----外层调用lock");lock.lock();try{System.out.println("----内层调用lock");}finally {// 这里故意注释,实现加锁次数和释放次数不一样// 由于加锁次数和释放次数不一样,第二个线程始终无法获取到锁,导致一直在等待。lock.unlock(); // 正常情况,加锁几次就要解锁几次}}finally {lock.unlock();}},"a").start();new Thread(() -> {lock.lock();try{System.out.println("b thread----外层调用lock");}finally {lock.unlock();}},"b").start();}
}

调用ReentrantLock的时候lock和unlock的数量最好要一一对应,否则可能会造成某一线程由于没有得到解锁指示而一直在等待解锁。

四、Synchronized的重入的实现机理

每个锁对象拥有一个锁计数器和一个指向持有该锁的线程的指针

当执行monitorenter时,如果目标锁对象的计数器为零,那么说明它没有被其他线程所持有,Java虚拟机会将该锁对象的持有线程设置为当前线程,并且将其计数器加1。

在目标锁对象的计数器不为零的情况下,如果锁对象的持有线程是当前线程,那么 Java 虚拟机可以将其计数器加1,否则需要等待,直至持有线程释放该锁。

当执行monitorexit时,Java虚拟机则需将锁对象的计数器减1。计数器为代表锁已被释放。


http://chatgpt.dhexx.cn/article/Qk1r9yLh.shtml

相关文章

可重入锁和不可重入锁 ReentrantLock synchronize

http://blog.csdn.net/qq838642798/article/details/65441415 https://www.cnblogs.com/dj3839/p/6580765.html 用lock来保证原子性(this.count这段代码称为临界区) 什么是原子性,就是不可分,从头执行到尾,不能被其他…

到底什么是重入锁,拜托,一次搞清楚!

相信大家在工作或者面试过程中经常听到重入锁这个概念,或者与关键字 synchrozied 的对比,栈长面试了这么多人,80%的面试者都没有答对或没有答到点上,或者把双重效验锁搞混了,哭笑不得。。 那么你对重入锁了解有多少呢&…

重入锁-ReentrantLock

ReentrantLock 一.重入锁的特点1)实现重进入功能2)分为公平锁和非公平锁: 二.ReentrantLock和AQS的关系 一.重入锁的特点 1)实现重进入功能 重进入是指任意线程获取锁之后能够再次获取该锁而不会被锁阻塞 锁的获取和释放过程如下: 线程再次获取锁。锁…

详述重入锁-ReentrantLock

什么是重入锁? 锁主要用来控制多线程访问的行为,对于同一个线程,如果连续两次对同一把锁进行lock,那么这个线程会被卡死在那里,这样的特性很不好,在实际的开发中,方法之间的调用方式错综复杂&a…

进行LDPC编码时扔掉了前面2Zc的信息位,为何如此设计?在解码时如何恢复?

好久没发文章了,拿去年的周报水一篇吧。 其实我也不是研究LDPC的,就是之前被导师提过这个问题,就看了一阵子。下面进入正文—— LDPC基础概念 对于这个问题,还是需要对LDPC码有初步的了解,下面先由一个普通的规则LDPC…

基于matlab的ldpc编码的构造,基于LDPC编码的GMSK调制与解调及matlab仿真实现(含录像)...

基于LDPC编码的GMSK调制与解调及matlab仿真实现(含录像)(开题报告,论文10700字,程序代码,录像) 摘 要 随着无线通信技术的不断发展与进步,数字电视广播、移动视频点播等对数据吞吐量要求很高的业务逐渐变得可能。为了在有限的带宽内用有限的发射功率保证信息在空间传…

ldpcMATLAB/ldpc的译码,matlab程序/LDPC编码的matlab实现/源码

ldpcMATLAB/ldpc的译码,matlab程序/LDPC编码的matlab实现/源码 1、ldpcMATLAB(ldpc编码的MATLAB例子,内容相对来说还是比较详细的。值得参考借鉴。) 2、LDPCmatlab(LDPC码的matlab实现,把解码的部分改过了&#xff…

通信算法之四十:5G NR LDPC编码译码性能仿真

1.码率1/5,增益14dB 2.码率1/12,增益17.8dB [ 相应MATLAB仿真代码。咨询qq:1279682290 ]

DVB-S2系统中LDPC译码器的实现 LDPC编码器的实现 FPGA DVB-S2、DVB-S2X LDPC 编码IP、LDPC译码 IP

DVB S2 LDPC 译码器.IP core IP Core特点: 1.全部代码由FPGA代码实现; 2.支持DVB-S2、DVB-S2X全部格式; 3.支持编码、译码; 4.支持标标准中16200、32400、64800三种帧长; 5.支持ACM、VCM、CCM模式,参…

UCI和数据复用在pusch上传输(第六部分)---ldpc编码

ldpc编码针对的是上下行数据的编码,也是5G最重要的一种编码。 1 TB块添加CRC 这个是和UCI POLAR区别的一个地方,UCI是对每个cb块添加crc. % Get transport block size after CRC attachment according to 38.212% 6.2.1 and 7.2.1, and assign CRC po…

【编码译码】基于matlab实现LDPC编码和解码

✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab仿真内容点击👇 智能优化算法 …

【LDPC编码】CDR系统中LDPC编码,LDPC编码的码长为9216

1.软件版本 matlab2013b 2.系统描述 在广播通信系统中,消息发送的速度和性能是一对矛盾,当发送速度快,则必然会降低消息的可靠性,当要求系统的性能,则必然会降低发送码率。为了提高系统的性能,并尽可能的…

5G LDPC编码流程

参照3GPP的标准文档,摘录其中下行共享信道与寻呼信道的LDPC编码流程,以便于进行对应的软件仿真 传输块加CRC校验   记待传输的数据块序列为 a 0 , a 1 , ⋯ , a A − 1 a_0,a_1,\cdots,a_{A-1} a0​,a1​,⋯,aA−1​,其中 A A A为传输块的负…

linux杀进程

linux学习心得 查看所有进行中的后台进程 命令 :ps aux ps命令查看应用进程。 后面的参数 -a : 显示现行终端机下的所有进程,包括其他用户的进程; -u :以用户为主的进程状态 ; x :通常与 a …

Linux找到进程并杀死

第一种情况: 写脚本的时候没没把程序杀死,再次启动发现端口被占用了,于是找到原来的端口然后kill掉重启 用下面2个命令可以: netstat -tunlp|grep 8080t:表示查看tcp u:表示查看udp n:表示端口…

在 Linux 中杀死一个进程

在 Linux 中,假如一个进程的 PID 为 3810,那么结束一个进程可以使用如下命令: $ kill -9 3810 以 Postman 为例,首先我们需要找到它的进程号,然后才能杀死。 查找进程号使用 ps 命令,不过有一个强大的参…

Linux命令行下杀死一个进程

在做项目的时候经常会出现程序死机、锁死、无响应等情况,这时候就需要找到程序相应的进程将其杀掉即可。步骤如下: 1.定位进程 top命令:可以实时动态地查看系统的整体运行情况,是一个综合了多方信息监测系统性能和运行信息的实用…

linux中进程杀不死解决办法

如图,多次在kill -9 此进程后依然存在 先说解决办法,输入过滤命令ps -ef|grep xxx(此处写要过滤的进程名字),例如 之后kill掉对应的进程号,如图 问题解决。 如果有多个子进程可以先过滤再一起杀死&#xf…

Linux中kill命令杀不掉进程的解决办法

1、进程杀不掉的原因有两种: (1)这个进程是僵尸进程 ; (2)此进程是"核心态"进程。 2、解决办法: (1)进入到“/proc/进程号”目录下,执行“cat stat…

Linux 批量杀进程

1.查需要杀死的进程 ps -ef | grep yum 2.去除掉里面的grep ps -ef | grep yum | grep -v grep 3.打印kill命令 ps -ef | grep yum | grep -v grep | awk {print "kill "$2} 4.执行kill命令 ps -ef | grep yum | grep -v grep | awk {print "kill "$2} …