【Java reentrantlock源码解读】

news2024/11/13 9:29:53

今天学习一下Java中lock的实现方式aqs

直接上图这是lock方法的实现类、分为公平锁和非公平锁两种。
在这里插入图片描述
先看非公平的实现方法、很暴力有木有,上来直接CAS(抢占锁的方法,是一个原子操作,没有学过的同学自行百度哦),如果抢占失败进入else方法,
在这里插入图片描述

这是else方法,进行了双&&短路运算符操作,咱们先从方法名去猜一猜,tryAcquire()这个方法应该是尝试去获取,如果返回false也就是获取不到才会去执行后面的acquireQueued(),看到这个queue我就联想到了aqs的数据结构双向等待队列。这些都是猜想,咱们继续看代码。
在这里插入图片描述
在这里插入图片描述

咱们接着看源码,这就是尝试获取锁调用的代码(非公平锁,公平锁等会看),if(c==0)表示锁未被占领然后就开始获取锁,获取成功返回true。else if表示当前获取锁的线程和持有锁的线程相等了,没错,这就是可重入锁了(可重入锁的好处就是不会发生死锁)。
在这里插入图片描述
综上所述,非公平锁是这么干的:首先上来直接获取锁(cas),如果获取不到发现当前锁没有被占领(if(c == 0))再次获取锁。
接着看公平锁是怎么干的。

并没有像非公平锁那样上来直接cas,温柔了很多。
在这里插入图片描述

公平锁同样分为两种情况,当c == 0表示当前锁没有被占领,公平锁比非公平锁多了hasQueuedPredecessors(),我猜这个方法是判断等待队列中是否存在节点,如果有节点就要遵循公平原则,没有节点才能cas去抢占,接下来看代码。
在这里插入图片描述

若 h == t则队列为空,直接返回false就会进入到抢占锁的代码中,咱们的猜测是正确的。
在这里插入图片描述

也就是说公平锁并没有像非公平锁一样一上来就抢占锁,也没有像非公平锁那样发现锁没有被占有就直接去抢占,而是先判断一下等待队列中还有没有其他线程。

看到这儿已经明白了公平锁和非公平锁是如何获取锁的,大家可以稍作休息,接下来接着看获取失败后是如何进入等待队列的,进入队列后又是如何再次获取锁的。

在这里插入图片描述
咱们先看addWaiter()方法,然后看acquireQueued(),大神写的代码太紧凑了。。。

首先创建了一个node节点包含当前线程,然后获取了尾部节点,如果尾部节点不为空,就尝试把该节点放到尾部。如果添加到尾部失败了就会进入enq()方法。我们接着看。
在这里插入图片描述

哈哈,一上来就是一个自旋,也就是说上一步的加入尾部顺利的话是不需要进入自旋的。
我们接着看自旋里干了什么,首先获取尾部节点,如果为空的话就初始化了头节点,并且将尾部节点指向头节点。
思考:也就说这个等待队列是在获取锁的时候才初始化的,对吧!并且初始化的队列是尾指向头的一个空节点(不包含线程信息new Node()构造函数没有传递任何内容)。
好,我们接着看代码,如果 t != null,就把当前节点设置为尾巴节点。
思考:为什么要自旋呢,一是为了初始化这个等待队列,二就涉及到了线程安全问题,这个队列是一个多条线程共享的资源,怎么保证线程安全问题呢,没错这儿的初始化队列方法和入队方法都是调用的保障线程安全的方法,即使发生了竞争导致失败了,依旧自旋继续尝试!总之最终要保证这个节点加入到等待队列中!
思考:如果是公平锁在加入等待队列的途中,发生了多条线程的竞争,会不会出现不公平的情况呢?
在这里插入图片描述

我们接着来看看acquireQueued(),继上一步的自旋成功入队以后,哈哈又开始自旋了,我们接着看自旋里做了什么。
node.predecessor()获取了当前节点的前一个节点,如果前一个节点是头节点就去抢占锁,(等待队列是一个双向fifo队列,并且头节点为空,这里的为空指的是node中的thread为null,setHead方法中体现)
思考:也就说抢占到锁的node不在等待队列中,排队最靠前的node在第二个节点,头节点永远是空的,没问题吧!

在这里插入图片描述
我们接着看shouldParkAfterFailedAcquire()和 parkAndCheckInterrupt()干了什么,需要注意的地方时这个if和上面的if是同级的,也就是说每次自旋都会反复执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1704256.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

香橙派 Kunpeng Pro使用教程:从零开始打造个人私密博客

一、引言 在这个日益互联的世界中,单板计算机已经成为创新和个性化解决方案的重要载体。而在单板计算机领域,香橙派 Kunpeng Pro凭借其强大的性能和灵活的应用潜力,正逐渐吸引着全球开发者和技术爱好者的目光。 作为一款集成了华为的鲲鹏处…

蓝牙模块、WiFi模块等无线通信模块使用规范

在当今的科技时代,无线通信模块已经广泛应用于各类电子设备中。特别是蓝牙模块、WiFi模块等无线模块,它们为设备间的通信提供了便利,使得我们的生活更加便捷和高效。然而,为了确保这些无线模块正常工作并避免可能的安全隐患&#…

I.MX6ULL的蜂鸣器实验-GPIO输出实验

系列文章目录 I.MX6ULL的蜂鸣器实验 I.MX6ULL的蜂鸣器实验 系列文章目录一、前言二、有源蜂鸣器简介三、硬件原理分析四、程序编写4.1程序编写前提工作4.2程序编写 五、编译下载验证5.1编写 Makefile 和链接脚本5.2编译下载 一、前言 在 I.MX6U-ALPHA 开发板上有一个有源蜂鸣器…

MYSQL框架结构

MYSQL框架结构 通过解析器和预处理生成解析树,预处理判断是否合法,如果合法则调用优化器去进行优化。

PYQT5点击Button执行多次问题解决方案(亲测)

PYQT5点击Button却执行多次问题 使用pyqt5时遇到问题,UI上按钮点击一次,对应的槽函数却执行了3遍 首先,确认函数名无冲突,UI button名无命名冲突,下图是简单的示例程序: 运行后,点击按钮&#…

探秘萤瓴优选短视频带货软件,开启新时代的电商创业方式

探秘萤瓴优选短视频带货软件,开启新时代的电商创业方式 随着移动互联网的飞速发展,电商行业迎来了前所未有的变革。短视频带货作为一种新兴的电商模式,以其直观、生动、互动性强的特点,迅速成为市场的新宠。在这个背景下&#xf…

银行软件测试有哪些测试点?一般银行的软件测试工作流程有哪些?

银行测试行业前景广阔,随着金融科技的快速发展和银行业务的不断创新,银行对软件测试的需求也在持续增长。软件测试在确保银行系统软件的稳定性、安全性和可靠性方面起着至关重要的作用,因此,银行测试岗位一直受到广泛的关注和重视…

TIM(Timer)简介

TIM(Timer)定时器介绍 定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时不仅具备基本的定时中断功能,而且…

基于香橙派 Ai Pro的ROS Qt人机交互软件部署指南

一,前言 最近收到了CSDN的邀请,对香橙派新出的Ai Pro进行测评: 说来也巧,其实香橙派本人对其映像挺深刻的,在2017年左右,本人刚上大学,当时是在淘宝购买树莓派,发现有个叫香橙派的国产板子,性能跟树莓派差不多吧,但是…

不是从APP store下载的APP在mac上一直提示有损坏,打不开怎么办?

1.点击设置 2.安全与隐私 3.通用看看允许从以下位置下载的APP是否有任何来源 4.如果没有,mac桌面点击🔍输入终端或Terminal 命令行输入下述代码: sudo spctl --master-disable 5.回车,输入mac开机密码。注意:此时密…

探索循环逻辑:for逻辑分支与容器遍历的深度剖析

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、引言:for逻辑与循环体的奥秘 二、for逻辑与循环体的结合使用 1. 函数与循环…

Spring-Cloud-OpenFeign源码解析-04-调用流程分析

在Spring-Cloud-OpenFeign源码解析-03-FeignClientFactoryBean分析到,通过Autowired或者Resource注入FeignClient实例的时候,实际上返回的是JDK动态代理对象,具体的实现逻辑在InvocationHandler的invoke方法中 回看ReflectiveFeign.newInsta…

Tower for Mac——高效版本控制的得力助手

在编程的世界里,版本控制是每一个开发者都离不开的工具。Tower for Mac,就是这样一款高效、易用的版本控制软件。 Tower for Mac拥有直观易用的界面,无论是提交代码、创建分支还是解决冲突,都能让开发者轻松应对。它支持多仓库管…

postman教程-5-发送put请求

领取资料,咨询答疑,请➕wei: June__Go 上一小节我们学习了postman发送post请求的方法,本小节我们讲解一下postman发送put请求的方法。 HTTP PUT 请求是一种用于传输数据的网络协议方法,它在客户端和服务器之间的通信中扮演着重…

EMQX 的初始IP改为自己的实际IP

分类 EMQX Dashboard(控制台): Dashboard提供了一个Web界面,用于管理和监控EMQX的运行状态。您可以通过配置dashboard.listeners.http.bind来设置Dashboard的监听地址和端口。例如,如果您想要Dashboard在所有网络接口上监听&#…

软件技术架构全面详解

软件架构全面详解 软件架构 这个与建筑设计架构类似,建筑设计架构师负责设计建筑物的整体结构、布局和功能分配。 而软件架构师,负责设计软件系统的整体组织结构、模块划分、和功能分配。 两者都需要考虑到业务功能、性能、可扩展性、安全性、以及用户体验等方面。 软件架…

基于Java+SpringBoot+Mybaties-plus+Vue+elememt + uniapp 新闻资讯 的设计与实现

一.项目介绍 本系统分为 后端 和 小程序端 后端:点击登录按钮 设置个人中心、 管理员账号数据维护、 基础数据维护、 短视频信息维护(包括查看短视频留言、短视频收藏)、 论坛维护(增删改查帖子信息,包括查…

Windows远程桌面是什么?

Windows远程桌面是一种远程桌面协议,允许用户通过网络连接到远程Windows计算机,并在本地操作远程计算机。它为用户提供了访问远程计算机的便利性,可以在不同地区的电脑或设备之间进行信息远程通信。 天联解决方案 在远程桌面技术中&#xff…

phpmyadmin漏洞汇总

phpmyadmin是一个非常常用的框架,所以学习它的常见漏洞是非常必要的。 参考大佬的文章进行自学:最全phpmyadmin漏洞汇总_phpmyadmin弱口令-CSDN博客 目录 phpmyadmin简介 查看phpmyadmin版本 漏洞及利用 万能密码登入 影响版本 漏洞POC 远程代码…

Ubuntu 20.04 上安装和配置 VNC

先决条件 请确保以具有 sudo 权限的用户身份登录。建议使用具有 sudo 权限的普通用户进行处理,而不是直接使用 root 用户。创建用户并加入 sudoers 可自行百度。 安装桌面环境 大多数服务器没有安装桌面环境,因此我们首先要安装轻量级桌面环境。 Ubu…