重入锁-ReentrantLock

article/2025/10/14 0:24:07

ReentrantLock

  • 一.重入锁的特点
    • 1)实现重进入功能
    • 2)分为公平锁和非公平锁:
  • 二.ReentrantLock和AQS的关系

一.重入锁的特点

1)实现重进入功能

重进入是指任意线程获取锁之后能够再次获取该锁而不会被锁阻塞
锁的获取和释放过程如下:

  1. 线程再次获取锁。锁需要去识别获取锁的线程是否为当前占据锁的线程,如果是则再次获取成功。
  2. 锁的最终释放。线程重复n次获取了锁,随后在第n次释放该锁后,其他线程能够获取到该锁。锁的最终释放要求锁对获取进行计数自增,计数表示当前锁被重复获取的次数,而锁被释放时,计数自减,当计数器等于0时表示锁已经成功释放了。

2)分为公平锁和非公平锁:

公平锁:

  1. 对先发起请求的线程即等待最久的线程优先满足,获取锁是顺序的,符合FIFO原则,不会产生线程饥饿
  2. 获取锁调用tryAcquire方法,与非公平锁不一样的地方在于判断条件多了hasQueuedPredecessors()方法,个方法判断队列中是否有其他节点,如果队列中还有其他节点,但是head后面还没关联节点 / 或者队列中head节点的后继节点关联的线程不是当前线程,如果是返回true,则表示有线程比当前线程更早地请求获取锁,因为要等待前驱节点获取并释放锁后才嫩继续获取到锁。

非公平锁(默认的):

  1. 获取是使用nonfairTryAcquire方法,只要CAS设置同步状态成功,则当前线程获取了锁。
  2. 非公平锁比公平锁效率更高,因为公平锁为了保证公平性会去切换线程导致上下文切换,存在额外的开销,所以非公平锁性能更好(所以作为默认的实现方式),保证了更大的吞吐量,但是可能会产生线程饥饿

二.ReentrantLock和AQS的关系

锁底层大多方法是使用AQS来实现的。

一般我们使用ReentrantLock都是直接创建一个对象,例如下面代码

Lock lock = new ReentrantLock();

下面我们看下ReentrantLock的构造函数

	public ReentrantLock() {//默认实现是以非公平锁实现的sync = new NonfairSync();}

从上面这个代码可以看出,我们要分析两个东西:一个是sync,一个是NofairSync(非公平锁):

//ReentrantLock实现了Lock
public class ReentrantLock implements Lock, java.io.Serializable {//我们刚刚要找的sync字段private final Sync sync;//Sync继承了AbstractQueuedSynchronizerabstract static class Sync extends AbstractQueuedSynchronizer {

1.sync分析:从上面源码可以看出sync是ReentrantLock内的属性,而且Sync是ReentrantLock的内部类,并且继承了AbstractQueuedSynchronizer,这个就是我们常常说的AQS,再进入AQS类看下:

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizerimplements java.io.Serializable {

从上面源码可以看出AbstractQueuedSynchronizer继承AbstractOwnableSynchronizer,也就是AQS继承AOS(后面都用AQS代表AbstractQueuedSynchronizer,AOS代表AbstractOwnableSynchronizer),我们再看看还没分析的NofairSync;

public class ReentrantLock implements Lock, java.io.Serializable {//NonfairSync继承Syncstatic final class NonfairSync extends Sync {

2.NofairSync分析:从上面源码可以看出NonfairSync也是ReentrantLock的内部类,并且继承Sync,难怪刚刚new NonfairSync()可以直接赋值给sync我们再看下ReentrantLock类的结构:

在这里插入图片描述
到这里我们可以总结下:
1.ReentrantLock下面有三个内部类:Sync,NonfairSync,FairSync
2.AQS继承AOS
2.Sync继承AQS
3.NonfairSync(非公平锁)、FairSync(公平锁)分别继承Sync

那我们可以得出UML图
在这里插入图片描述
AQS和ReentrantLock参考源码分析:
https://guguoyu.blog.csdn.net/article/details/90485326


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

相关文章

详述重入锁-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} …

linux 找出谁杀了进程

目录 Linux Signal 到底是什么信号 OOM 谁发的信号 systemtap audit 案例与总结 服务端的程序,一般都希望比较长时间的运行,比如7*24小时。不过,程序也需要更新,比如修Bug,比如增加新功能,比如修复增…

Linux操作系统之批量杀死进程

前言 在Linux操作系统中,一般常用的杀死进程的命令是 kill 、 pkill 、 killall ,根据杀死单个进程拓展至批量杀死进程。 1、查看指定名称的进程,如下查看运行wps程序的进程: ps -ef | grep wps | grep -v grep 结果如下&…

在 VUE中,动态加载JS文件

需求 在vue组件中需要调用的函数方法名是相同的(接口相同),但是按照页面不同需要导入不同JS文件 。如下: 然而上面这种写法肯定是行不通的,但表达的需求很明确。根据menuId的不同从JS文件中获取方法 解决方案 promi…