cdr做好排班怎么做网站/百度站长提交
一、ReentrantLock
ReentrantLock
是 java
JUC
中的一个可重入锁,在上篇文章讲解 AQS
源码的时候提到 ReentrantLock
锁是基于 AQS
实现的,那是如何使用的 AQS
呢,本篇文章一起带大家看下 ReentrantLock
的源码。
在 AQS
中,如果需要使用AQS
的特征则需要子类根据使用的场景,重写下面方法,
//查询是否正在独占资源,condition会使用
boolean isHeldExclusively()
//独占模式,尝试获取资源,成功则返回true,失败则返回false
boolean tryAcquire(int arg)
//独占模式,尝试释放资源,成功则返回true,失败则返回false
boolean tryRelease(int arg)
//共享模式,尝试获取资源,如果返回负数表示失败,否则表示成功。
int tryAcquireShared(int arg)
//共享模式,尝试释放资源,成功则返回true,失败则返回false。
boolean tryReleaseShared(int arg)
由于这里 ReentrantLock
锁的特性,所以下面我们只需关注独占模式下的几个方法即可。
说明:本文中关于 AQS
中的方法没有做过多的解释,不了解的小伙伴可以看下这篇对 AQS
源码分析的文章,和当前文章在同一专栏:
https://blog.csdn.net/qq_43692950/article/details/129367736
下面一起开始 ReentrantLock
源码的分析:
二、ReentrantLock 的 Sync、FairSync、NonfairSync
2.1 Sync、FairSync、NonfairSync
在声明 ReentrantLock
锁时,有两种方式,一种是无参构造函数,一种则需要指定一个 fair
参数:
new ReentrantLock();
new ReentrantLock(false);
当使用无参构造函数声明时,则是创建了一个 NonfairSync
对象:
通过有参的构造函数,则根据传入的 fair
可以选择创建一个 FairSync
对象:
其实这里也不难理解 NonfairSync
和 FairSync
其实就是ReentrantLock
锁中的非公平锁和公平锁两种类型。
点到这两个类中,可以看到都继承自 Sync
类:
而 Sync
类,则继承了 AQS
:
到这里了,我们寻找几个关键的方法,在AQS
中独占模式下,两大关键的方法是交由子类进行实现的,分别是 tryAcquire
尝试获取资源,和 tryRelease
尝试释放资源。
首先来看 tryAcquire
尝试获取资源:
通过 Sync
类的实现源码发现并没有重写 tryAcquire
方法,那该方法肯定在下面的子类FairSync
和 NonfairSync
,分别看下源码确实存在重写的方法:
2.2 NonfairSync 下的 tryAcquire
首先看下 NonfairSync
的 tryAcquire
实现逻辑,可以看到又调用了 nonfairTryAcquire
就是 Sync
类中的 nonfairTryAcquire
,从命名上可以分析出就是非公平锁的尝试获取资源,直观就是非公平锁下获取锁操作:
进入到 Sync
类中的 nonfairTryAcquire
中,可以看到首先获取到 AQS
中的共享资源 state
,如果 state
等于 0
,则将 state
的值修改为 acquires
(默认为1
,下面会分析到),并设置AQS
的独占线程为当前线程,并返回 true
,说白了不就是获取到锁了吗,那就可以理解为 state
等于 0
即是无锁的状态,下面将 state
的值修改为 acquires
就是获取到锁了,改变资源的状态:
接着如果 state
的值不是 0
,则当前锁已经被别的线程持有了,这里又判断了下,如果持有锁的线程正好是当前的线程,那不就是锁的重入吗,这种情况下可以直接获得锁,不过这里为了记录重入的次数,对 state
共享资源进行了 + acquires
操作,其实就是 +1
操作。
如果都没有成功,那此时则获取锁失败,返回 false
2.3 FairSync下的 tryAcquire
在 FairSync
类下的 tryAcquire
方法中,和前面 NonfairSync
类似,但不同的是,在获取到锁时,也就是拿到 state
等于 0
,进行修改资源时,多了步 hasQueuedPredecessors
的判断:
下面可以进到 hasQueuedPredecessors
的方法中,可以看到是由 AQS
提供的方法,主要就是判断当前节点线程的前面是否还有等待的线程,因为 FairSync
实现的是公平锁的原则,如果当前线程前面还有等待线程,则获取锁资源也轮不到自个,让前面的老大先来:
hasQueuedPredecessors
方法理解后,其余的逻辑则和 NonfairSync
中的一致了。
2.4 tryRelease
到这里已经了解到了tryAcquire
尝试获取资源的逻辑,上面提到了两个重要方法,还有一个 tryRelease
没有分析逻辑,还是首先看 Sync
类中是否有重写该方法:
通过源码可以看到,在 Sync
类中就已经对 tryRelease
进行了重写,而 NonfairSync
和 FairSync
中都没有重写该方法,那释放资源就是走的 Sync
类下的 tryRelease
方法:
在该方法中,可以看到首先还是获取到了 AQS
中的 state
共享资源,然后对该资源进行 - releases
(默认releases
为1
,下面会提到 )操作,其实就是 -1
操作:
接着判断了下,如果当前线程不是持有锁线程,就抛出异常,也好理解,没有持有锁的线程跑过来释放锁,那肯定有问题了呀。
接着再进行判断 state
是不是等于 0
,上面讲到在锁重入的情况下,记录重入的次数是对 state
进行 +1
操作,而这边又对 state
进行 -1
操作,如果减到最后 state
有成了最初的 0
,那不就是重入的锁和当前持有的锁都释放完了吗,这个时候就可以将持有锁的线程置为空了,并修改最新的 state
:
看到这里就会发现获取锁和释放锁,无非就是对 AQS
中的共享资源进行操作。理解了这两大核心的方法后,下面就可以看如何运用在 ReentrantLock
中的了。
三、lock.lock()
在 ReentrantLock
中,需要获取锁时,直接使用 lock.lock()
即可,那 lock.lock()
到底做了什么呢,点到该方法中,可以看到是调用的 Sync
的 lock
方法,而 Sync
中的lock
方法是抽象方法,具体实现肯定在子类的 NonfairSync、 FairSync
中。
3.1 NonfairSync.lock()
首先看点 NonfairSync
非公平锁中的 lock
方法,直接进行了将 AQS
中的共享资源 state
由 0
改为 1
,如果修改成功,根据上面分析的结论不就是获取锁成功了吗,可以将AQS
中的独占线程设为自己了。但是如果其他线程修改成功了,这里使用 CAS
就会修改失败,因此就会进到 acquire
方法,注意这里传递的参数默认就是 1
,对应着前面括号中的说明:
而 acquire
方法,就是 AQS
中的独占模式获取同步资源的逻辑,会调用当前方法的 tryAcquire
尝试获取资源,如果获取不到,则加入到 AQS
的阻塞队列并阻塞挂起线程。
关于acquire
方法的源码解读可以参考文章开始的链接中对 AQS
源码的解读。
3.2 FairSync.lock()
在 FairSync
公平锁中,由于需要遵循先进先出的原则,这里没有直接已粗暴的形式对 state
进行修改,而是直接调用了 AQS
中的 acquire
方法,而 acquire
方法又会调用当前类的 tryAcquire
获取资源。
但在当前类的 tryAcquire
方法中,如果获取到了资源,会接着进行判断当前线程的前面是否还有等待的线程,如果有则让出来让别人获取资源,因此就遵循了公平锁的原则,注意这里传递的参数默认就是 1
,同样对应着前面括号中的说明:
同样 tryAcquire
尝试获取资源,如果获取不到,则加入到 AQS
的阻塞队列并阻塞挂起线程。
四、lock.unlock()
上面了解到了 lock
的逻辑,既然上锁了肯定需要解锁,下面点到 unlock()
方法中,可以看到直接使用了 Sync
的 release
方法释放资源,其实是 AQS
中的 release
方法,注意这里传递的参数默认就是 1
,同样对应着前面括号中的说明:
在 AQS
的release
方法中,首先会调用 Sync
类的 tryRelease
释放资源,然后对已阻塞的线程进行唤醒:
关于release
方法的源码解读可以参考文章开始的链接中对 AQS
源码的解读。
五、总结
通过阅读 ReentrantLock
的源码可以发现,大量依赖于 AQS
中提供的方法,所以在阅读前一定要理解下 AQS
的作用和功能。
相关文章:

ReentrantLock 源码解读
一、ReentrantLock ReentrantLock 是 java JUC 中的一个可重入锁,在上篇文章讲解 AQS 源码的时候提到 ReentrantLock 锁是基于 AQS 实现的,那是如何使用的 AQS 呢,本篇文章一起带大家看下 ReentrantLock 的源码。 在 AQS 中,如果…...

【算法】六大排序 插入排序 希尔排序 选择排序 堆排序 冒泡排序 快速排序
本章的所有代码可以访问这里 排序 一 一、排序的概念及其运用1.1排序的概念1.2 常见的排序算法二、常见排序算法的实现1、直接插入排序2、希尔排序3、选择排序4、堆排序5、冒泡排序6、快速排序6.1霍尔法6.2挖坑法6.3前后指针法7、快速排序非递归一、排序的概念及其运用 1.1排序…...

类和对象万字详解
目录 一、面向对象与面向过程的区别 面向过程: 面向对象: 二、类的引入 class与struct爱恨情仇 class的语法 类的定义: 类的限定访问符 类的实例化 类对象模型 this指针的应用 三、封装 四、类的六个默认成员函数 构造函数 再谈…...

如何使用码匠连接 CouchDB
目录 在码匠中集成 CouchDB 在码匠中使用 CouchDB 关于码匠 CouchDB 是一种开源的 NoSQL 数据库服务,它使用基于文档的数据模型来存储数据。CouchDB 的数据源提供了高度可扩展性、高可用性和分布式性质。它支持跨多个节点的数据同步和复制,可以在多个…...

MySQL对表操作
结束了上一章内容,我们对数据库的操作有一定的了解,本章内容就是针对表中的数据进行操作的。 针对表中数据的操作绝大部分都是增删改查(CRUD),CRUD也就是四个单词的缩写: 增加(Create)、查询(Retrieve)、…...

springboot3整合mybatis遇到的坑
本人不经常写java,本文仅作问题记录,如有问题请把不吝赐教。 坑1、Property sqlSessionFactory or sqlSessionTemplate are required Caused by: java.lang.IllegalArgumentException: Property sqlSessionFactory or sqlSessionTemplate are required…...

SpringBoot+Spring常用注解总结
1. SpringBootApplication 这里先单独拎出SpringBootApplication 注解说一下,虽然我们一般不会主动去使用它。 SpringBootApplication public class SpringSecurityJwtGuideApplication {public static void main(java.lang.String[] args) {SpringApplication.ru…...

优化UnRaid容器的WebUI端口设置实现应用快捷访问的方法
文章目录前言详细流程前言 自从入了UnRaid的坑,发现Docker真是个好东西,各种各样的应用工具层出不穷,可以大大提高生产效率。然而在安装Docker应用后,对于如何方便的访问该应用,各个应用服务提供者给出的解决方案不是…...

Android Framework-管理Activity和组件运行状态的系统进程—— ActivityManagerService(AMS)
ActivityManagerService(AMS)是Android提供的一个用于管理Activity(和其他组件)运行状态的系统进程 AMS功能概述 和WMS一样,AMS也是寄存于systemServer中的。它会在系统启动时,创建一个线程来循环处理客户…...

【C语言】结构体和共用体
目录一、结构体(一)结构体声明(二)结构体变量定义(三)结构体变量的初始化(四)结构体的引用(五)结构体数组二、共用体(一)共用体定义&a…...

微搭低代码从入门到实战
低代码从21年起开始成为热点,至今已经发展了两年多的时间。微搭作为腾讯云旗下的低码产品也历经多轮优化。 不同人选择低代码有不同的理由,有的是初创企业希望低代码来提升运营效率的。有的是传统企业,希望借助低代码来改造现有系统提供移动…...

AM5728(AM5708)开发实战之安装Debian 10桌面操作系统
一 环境搭建 准备一个SD卡启动卡,能够正常引导板卡启动,后续会把Debian 10镜像安装到SD卡ext4分区 准备两个U盘,一个格式化成fat32文件系统,另一个格式化成ext4文件系统 下载Debian 10镜像,镜像名字为debian-10.4.0-a…...

ip-guardip-guard如何通过准入网关对指定的服务器进行通讯加密保护?
1、准入网关在高级配置设置受保护服务器; WEB管理界面【系统工具】,点击【配置管理】,点击参数设置,进入高级配置界面,输入配置内容即可。 [ControlServer]...

JavaScript基础语法
目录 1.初识JavaScript 1.1背景知识 1.2JS的三种书写方式 行内式 内嵌式 外部式 2.语法简介 2.1变量的使用 变量创建方法 动态类型 2.2基本数据类型 2.3数组 js数组创建方式 遍历方式 添加元素:尾插 编辑删除元素:splice 2.4函数 格式 函数表达式 作用域…...

《SQL基础》17. InnoDB引擎
InnoDB引擎InnoDB引擎逻辑存储结构架构内存结构磁盘结构后台线程事务原理事务基础redo logundo logMVCC基本概念隐式字段undo log版本链readView原理分析InnoDB引擎 逻辑存储结构 InnoDB的逻辑存储结构如下图所示: 表空间 表空间是InnoDB存储引擎逻辑结构的最高层…...

api接口详解大全
api接口详解大全?优秀的设计是产品变得卓越的原因设计API意味着提供有效的接口,可以帮助API使用者更好地了解、使用和集成,同时帮助人们有效地维护它每个产品都需要使用手册,API也不例外在API领域,可以将设计视为服务器和客户端之…...

为什么要用VR全景?5个答案告诉你
看中了刚上市的一款新车,再也不用等车展、去4s店才能仔细观赏,点开手机就能“置身”车内近距离观看每一处细节,点击关灯开灯、关门关门,除了摸不到,和在现场几乎没有区别; 准备买房的时候,没人愿…...

常用的深度学习优化方式
全连接层 PyTorch中的全连接层(Fully Connected Layer)也被称为线性层(Linear Layer),是神经网络中最常用的一种层。全连接层将输入数据的每个元素与该层中的每个神经元相连接,输出结果是输入数据与该层的…...

全面吃透Java Stream流操作,让代码更加的优雅
文章目录1 认识Stream流1.1 什么是流1.2 流与集合1.2.1 流只能遍历一次1.2.2 外部迭代和内部迭代1.3 流操作1.3.1 中间操作1.3.2 终端操作1.3.3 使用流2 学会使用Stream流2.1 筛选和切片2.1.1 用谓词筛选2.1.2 筛选各异的元素2.1.3 截短流2.1.4 跳过元素2.2 映射2.2.1 map方法2…...

机器学习学习记录1:假设空间
我们可以把学习过程看作一个在所有假设组成的空间中进行搜索的过程,搜索目标是找到与训练集"匹配" 的假设,即能够将训练集中的瓜判断正确的假设.假设的表示一旦确定,假设空间及其规模大小就确定了.对于西瓜问题,这里我们…...

开源工具系列5:DependencyCheck
Dependency-Check 是 OWASP(Open Web Application Security Project)的一个实用开源程序,用于识别项目依赖项并检查是否存在任何已知的,公开披露的漏洞。 DependencyCheck 是什么 Dependency-Check 是 OWASP(Open Web …...

JDBC知识点全面总结2:JDBC实战编写CRUD
二.JDBC知识点全面总结1:JDBC实战编写CRUD 1.JDBC重要接口? 2.Driver和DriverMangement的关系? 3.JAVA与数据库连接 4.JAVA中使用statement来执行sql语句时,拼接字符串的sql注入问题? 5.使用preparedstatement进行…...

java - 数据结构,算法,排序
一、概念 1.1、排序 排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 平时的上下文中,如果提到排序,通常指的是排升序(非降序)。 通常意义上的排序&#…...

二叉树经典14题——初学二叉树必会的简单题
此篇皆为leetcode、牛客中的简单题型和二叉树基础操作,无需做过多讲解,仅付最优解。有需要的小伙伴直接私信我~ 目录 1.二叉树的节点个数 2.二叉树叶子节点个数 3.二叉树第K层节点个数 4.查找值为X的节点 5.leetcode——二叉树的最大深度 6.leetc…...

基于NMOSFET的电平转换电路设计
一、概述: 在单片机系统中,5V、3.3V是芯片常用的电平。而在传输协议中(如IIC、SPI等协议),存在芯片与芯片的高电平和低电平定义的范围不一样,所以需要存在一个电平转换电路,来使芯片与芯片之间顺利的传输。 二、前置…...

mongoDB搭建集群
(学习自黑马)下载对应linux版本MongoDB源码下载地址:https://www.mongodb.com/download-center#community目前在一台服务器开三个端口模拟三个mongodb, 配置一个主节点27017,一个从节点27018,一个仲裁者27019配置主节点,副节点,仲裁节点(下面的创建文件一共有三份,通…...

[深入理解SSD系列 闪存2.1.5] NAND FLASH基本读操作及原理_NAND FLASH Read Operation源码实现
前言 上面是我使用的NAND FLASH的硬件原理图,面对这些引脚,很难明白他们是什么含义, 下面先来个热身: 问1. 原理图上NAND FLASH只有数据线,怎么传输地址? 答1.在DATA0~DATA7上既传输数据,又传输地址 当ALE为高电平时传输的是地址, 问2. 从NAND FLASH芯片手册可知,要…...

最新 JVM 面试经典问题
文章目录 说说JVM的内存布局?知道new一个对象的过程吗?知道双亲委派模型吗?说说有哪些垃圾回收算法?标记-清除复制算法标记-整理那么什么是GC ROOT?有哪些GC ROOT?垃圾回收器了解吗?年轻代和老年代都有哪些垃圾回收器?G1的原理了解吗?什么时候会触发YGC和FGC?对象什么…...

HTML5 和 CSS3 的新特性
目标能够说出 3~5 个 HTML5 新增布局和表单标签能够说出 CSS3 的新增特性有哪些HTML5新特性概述HTML5 的新增特性主要是针对于以前的不足,增加了一些新的标签、新的表单和新的表单属性等。 这些新特性都有兼容性问题,基本是 IE9 以上版本的浏览器才支持&…...

Vulnhub系列:FristLeaks
一、配置靶机环境以往的靶机,本人是在virtual box中,去配置,和vm上的kali进行联动,但是这个靶机需要DHCP,以往的方式可能不太行了,或者可以在virtual box中桥接成统一网卡。下面介绍下本人最有用的方法&…...