【Java reentrantlock源码解读】

今天学习一下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.mzph.cn/diannao/17144.shtml

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

相关文章

软件测试面试题(六)

一:质量的八大特性是什么?各种特性的定义? 功能性:软件所实现的功能达到它的设计规范和满足用户需求的程度 性能:在规定的条件下实现软件功能所需的响应时间和计算机资源(CPU、内存、磁盘空间和吞吐量&…

MagicaCloth2中文文档

提示:经搬运者测试,在ecs1.0中运行最为良好 如何安装 英语日语 目录 [隐藏] 1 如何安装2 样本运行测试3 可以删除示例文件夹4 如何更新5 发生错误时该怎么办6 如何卸载7 如何检查版本 如何安装 MagicaCloth2 需要 Unity 2021.3.16 (LTS&…

jQuery效果2

jQuery 一、属性操作1.内容2.列子,购物车模块-全选 二、内容文本值1.内容2.列子,增减商品和小记 三、元素操作(遍历,创建,删除,添加)1.遍历2.例子,购物车模块,计算总件数和总额3.创建…

【简单介绍下线性回归模型】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…

Habicht定理中有关子结式命题3.4.6的证明

个人认为红色区域有问题,因为 deg ⁡ ( ϕ ( S j ) ) r \deg{\left( \phi\left( S_{j} \right) \right) r} deg(ϕ(Sj​))r,当 i ≥ r i \geq r i≥r时, s u b r e s i ( ϕ ( S j 1 ) , ϕ ( S j ) ) subres_{i}\left( \phi(S_{j 1}),\p…

技术速递|使用 C# 集合表达式重构代码

作者:David Pine 排版:Alan Wang 本文是系列文章的第二篇,该系列文章涵盖了探索 C# 12功能的各种重构场景。在这篇文章中,我们将了解如何使用集合表达式重构代码,我们将学习集合初始化器、各种表达式用法、支持的集合目…

函数调用时长的关键点:揭秘参数位置的秘密

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、默认参数的秘密 示例代码 二、关键字参数与位置参数的舞蹈 示例代码 总结 一、默认参…

Linux下SuiteSparse的下载与编译

前言 SuiteSparse 是一个用于稀疏矩阵计算的开源库,它提供了一系列高效的算法和工具,用于解决线性代数和优化问题中的稀疏矩阵操作。 SuiteSparse Matrix Collection 是由 Tim Davis 创建和维护的一个稀疏矩阵集合,其中包含了各种各样的真实…

Java学习:电影查询简单系统

1.创建一个movice的对象来存放电影 里面设置构造器(有参和无参) package com.movie;public class movice {//创建一个movice的对象存放电影private int id;private String name;private double price;private double score;private String diector;pri…

PyCharm面板ctrl+鼠标滚轮放大缩小代码

1.【File】➡【Settings】 2.点击【Keymap】,在右边搜索框中搜incre,双击出现的【Increase Font Size】 3.在弹出的提示框中选择【Add Mouse Shortcut】 4.弹出下面的提示框后,键盘按住【ctrl】,并且上滑鼠标滚轮。然后点击【O…

高等数学导学

高数内容线 1.极限2.导数3.积分一元函数多元函数: 说明 高等数学主要讲这三个东西,上下两册内容:上册主要讲一元,下册讲多元 但是一元是多元的基础,必须得掌握好,下册的多元函数才能学的好 七八章讲微分和解…

ResizeObserver loop completed with undelivered notifications.

报错信息 ResizeObserver loop completed with undelivered notifications. 来源 在用vue3 element-plus写项目的时候报的错,经过排查法,发现是element-plus的el-table组件引起的错误。 经过初步排查,这个错误并不是vue以及element-plus…

【前端每日基础】day24——DOM操作

DOM 操作 获取元素 要对网页中的元素进行操作,首先需要获取这些元素。常用的方法有: document.getElementById(id): 获取具有指定id的元素。 document.getElementsByClassName(className): 获取具有指定类名的所有元素,返回HTMLCollection。…

Redis数据类型(上篇)

前提:(key代表键) Redis常用的命令 命令作用keys *查看当前库所有的keyexists key判断某个key是否存在type key查看key是什么类型del key 删除指定的keyunlink key非阻塞删除,仅仅将keys从keyspace元数据中删除,真正的…

vueRouter路由总结

https://blog.csdn.net/qq_24767091/article/details/119326884

中国电子节能技术协会数据安全专业委员会筹备会暨标准征集启动会即将开幕

导读:“以高效、安全、绿色数据底座铸就美好未来”为主题的2024数据安全与绿色发展研讨会,中国电子节能技术协会数据安全专业委员会筹备会暨标准征集启动会即将开幕。 绿色发展是高质量发展的底座,绿色化是新一轮科技革命和产业变革的重要趋势…

力扣hot 100:49. 字母异位词分组(python C++)

目录 题目描述:题解(python):(方法一:排序)代码解析代码运行解析 题解(C):(方法一:排序)代码解析&运行解析 原题目链接…

机器学习笔记——K近邻算法、手写数字识别

KNN算法 “物以类聚,人以群分”相似的数据往往拥有相同的类别 其大概原理就是一个样本归到哪一类,当前样本需要归到频次最高的哪个类去 也就是说有一个待分类的样本,然后跟他周围的k个样本来看,k中哪一个类最多,待分类…

Oracle数据库Day01-SELECT语句

一、SQL语句 1. 环境配置与准备 linux端oracle用户打开监听//查看监听状态与开始监听 lsnrctl status lsnrctl start开启数据库sqlplus / as sysdba startup;解锁hr用户样例数据库,给hr用户设置密码并且连接alter user hr account unlock; alter user hr identifie…

2024爆款神器!会声会影2024旗舰版,让你的视频制作技能暴涨,不学真的亏大了!

在数字内容创作的时代,视频编辑已经成为连接创意与现实的重要桥梁。无论是个人Vlog制作、在线教育课程、企业宣传还是专业影视制作,高效而强大的视频编辑软件成为了必不可少的工具。会声会影2024旗舰版,作为一款集先进技术与用户友好界面设计…