扒一扒ReentrantLock以及AQS实现原理

AQS(AbstractQueuedSynchronizer) 面试题的代码解析,涵盖核心原理和常见面试考点 CLH队列:双向链表实现公平等待,节点状态(waitStatus)控制唤醒逻辑,核心是“FIFO”原则;state管理volatile保证可见性,CAS保证原子修改,不同组件通过state语义差异化实现功能;两种模式独占模式:实现tryAcquiretryRelease(如共享模式:实现(如阻塞与唤醒:依赖unpark(),通过节点状态(SIGNAL)协调唤醒时机;条件队列Condition对应独立单向链表,await()转移到条件队列,signal()转移回同步队列,需持有锁才能操作。 阅读详情

这篇文章,我们来聊聊面试的时候比较有杀伤力的一个问题:聊聊你对AQS的理解?

之前有同学反馈,去互联网公司面试,面试官聊到并发时就问到了这个问题。当时那位同学内心估计受到了一万点伤害。。。

因为首先,很多人还真的连AQS是什么都不知道,可能听都没听说过。或者有的人听说过AQS这个名词,但是可能连具体全称怎么拼写都不知道。

更有甚者,可能会说:AQS?是不是一种思想?我们平时开发怎么来用AQS?

总体来说,很多同学估计都对AQS有一种云里雾里的感觉,如果用搜索引擎查一下AQS是什么?看几篇文章,估计就直接放弃了,因为密密麻麻的文字,实在是看不懂!

所以,基于上述痛点,咱们这篇文章,就用最简单的大白话配合N多张手绘图,给大家讲清楚AQS到底是什么?让各位同学面试被问到这个问题时,不至于不知所措。

ReentrantLock和AQS的关系

首先我们来看看,如果用Java并发包下的ReentrantLock来加锁和释放锁,是个什么样的感觉?

这个基本学过Java的同学应该都会吧,毕竟这个是java并发基本API的使用,应该每个人都是学过的,所以我们直接看一下代码就好了:

上面那段代码应该不难理解吧,无非就是搞一个Lock对象,然后加锁和释放锁。

你这时可能会问,这个跟AQS有啥关系?关系大了去了!因为Java并发包下很多API都是基于AQS来实现的加锁和释放锁等功能的,AQS是Java并发包的基础类。

举个例子,比如说ReentrantLock、ReentrantReadWriteLock底层都是基于AQS来实现的。

那么AQS的全称是什么呢?AbstractQueuedSynchronizer,抽象队列同步器。给大家画一个图先,看一下ReentrantLock和AQS之间的关系。

我们来看上面的图。说白了,ReentrantLock内部包含了一个AQS对象,也就是
AbstractQueuedSynchronizer类型的对象。这个AQS对象就是ReentrantLock可以实现加锁和释放锁的关键性的核心组件。

ReentrantLock加锁和释放锁的底层原理

​好了,那么现在如果有一个线程过来尝试用ReentrantLock的lock()方法进行加锁,会发生什么事情呢?

很简单,这个AQS对象内部有一个核心的变量叫做state,是int类型的,代表了加锁的状态。初始状态下,这个state的值是0。

另外,这个AQS内部还有一个关键变量,用来记录当前加锁的是哪个线程,初始化状态下,这个变量是null。​

接着线程1跑过来调用ReentrantLock的lock()方法尝试进行加锁,这个加锁的过程,直接就是用CAS操作将state值从0变为1。

如果不知道CAS是啥的,请看上篇文章,《 ​ Java8中的LongAdder类,大大提升CAS性能 ​ !》。

如果之前没人加过锁,那么state的值肯定是0,此时线程1就可以加锁成功。

一旦线程1加锁成功了之后,就可以设置当前加锁线程是自己。所以大家看下面的图,就是线程1跑过来加锁的一个过程。

​其实看到这儿,大家应该对所谓的AQS有感觉了。说白了,就是并发包里的一个核心组件,里面有state变量、加锁线程变量等核心的东西,维护了加锁状态。

你会发现,ReentrantLock这种东西只是一个外层的API,内核中的锁机制实现都是依赖AQS组件的。

这个ReentrantLock之所以用Reentrant打头,意思就是他是一个可重入锁。

可重入锁的意思,就是你可以对一个ReentrantLock对象多次执行lock()加锁和unlock()释放锁,也就是可以对一个锁加多次,叫做可重入加锁。

大家看明白了那个state变量之后,就知道了如何进行可重入加锁!

其实每次线程1可重入加锁一次,会判断一下当前加锁线程就是自己,那么他自己就可以可重入多次加锁,每次加锁就是把state的值给累加1,别的没啥变化。

接着,如果线程1加锁了之后,线程2跑过来加锁会怎么样呢?

我们来看看锁的互斥是如何实现的?线程2跑过来一下看到,哎呀!state的值不是0啊?所以CAS操作将state从0变为1的过程会失败,因为state的值当前为1,说明已经有人加锁了!

接着线程2会看一下,是不是自己之前加的锁啊?当然不是了,“加锁线程”这个变量明确记录了是线程1占用了这个锁,所以线程2此时就是加锁失败。

给大家来一张图,一起来感受一下这个过程:​

接着,线程2会将自己放入AQS中的一个等待队列,因为自己尝试加锁失败了,此时就要将自己放入队列中来等待,等待线程1释放锁之后,自己就可以重新尝试加锁了

所以大家可以看到,AQS是如此的核心!AQS内部还有一个等待队列,专门放那些加锁失败的线程!

同样,给大家来一张图,一起感受一下:

接着,线程1在执行完自己的业务逻辑代码之后,就会释放锁!他释放锁的过程非常的简单,就是将AQS内的state变量的值递减1,如果state值为0,则彻底释放锁,会将“加锁线程”变量也设置为null!

整个过程,参见下图:

​接下来,会从等待队列的队头唤醒线程2重新尝试加锁。

好!线程2现在就重新尝试加锁,这时还是用CAS操作将state从0变为1,此时就会成功,成功之后代表加锁成功,就会将state设置为1。

此外,还要把“加锁线程”设置为线程2自己,同时线程2自己就从等待队列中出队了。

最后再来一张图,大家来看看这个过程。​

总结

​OK,本文到这里为止,基本借着ReentrantLock的加锁和释放锁的过程,给大家讲清楚了其底层依赖的AQS的核心原理。

基本上大家把这篇文章看懂,以后再也不会担心面试的时候被问到:谈谈你对AQS的理解这种问题了。

其实一句话总结AQS就是一个并发包的基础组件,用来实现各种锁,各种同步组件的。它包含了state变量、加锁线程、等待队列等并发中的核心组件。​

高频面试题之AQS核心原理分析 概念扫盲: ReentrantLock: 独占锁/排他锁 CountDownLatch 计数器 递减 CyclicBarrier 计数器 自增 SemaPhore 信号量 AQS=AbstractQueuedSynchronizer类, 即抽象的同步队列==》解决数据安全问题(并行转换为串行)。 造成数据安全问题的原因是什么?多线程,并发。 假设多个线程对count进行处理: 假设我们启动100个线程对count进行自增操作: 正常执行后: 得到的结果是一个小于等于1 阅读详情

相关推荐

50道Java经典面试题总结

(1)Semaphore 同步器特征:经典的信号量,通过计数器控制对共享资源的访问Semaphore(int count): 创建拥有 count 个许可证的信号量acquire()/acquire(int num) : 获取 1/num 个许可证release/release(int num) : 释放 1/num 个许可证(2)CountDownLatch 同步器特征:必须发生指定数量的事件后才可以继续运行 (比如赛跑比赛,裁判喊出 3,2,1 之后大家才同时跑)

2401_83470102的博客 1020

Java面试--AQS

AQS

小刺猬 5564

从ReentrantLock理解AQS的原理及应用总结

本文介绍了Java中的AbstractQueuedSynchronizer(AQS),重点讲解了其在实现ReentrantLock等同步器中的应用。文章分析了AQS的基本概念、工作原理及关键数据结构,并探讨了其在多线程竞争中的线程排队与唤醒机制。通过对AQS实现的深入剖析,帮助开发者更好地理解并发编程中的锁机制和自定义同步器的实现。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 171万+

JAVA面试题|AQS详细剖析

JAVA基础篇面试题 文章目录JAVA基础篇面试题1. 线程等待唤醒的实现方法2. 介绍一下LockSupport3. AQS是什么4. AQS的核心原理5. 公平锁与非公平锁的区别6. 请讲述非公平锁加锁解锁的具体流程 1. 线程等待唤醒的实现方法 Object对象中的wait()方法可以让线程等待,使用Object中的notify()方法唤醒线程; 必须都在同步代码块内使用; 调用wait,notify的对象是加锁对象; notify必须在wait后执行才能唤醒; wait后能释放锁对象,线程处

qq_37419449的博客 1万+

ADS负载牵引仿真避坑指南:从零开始搞定Loadpull模板设置

本文是一份针对ADS负载牵引仿真的深度避坑指南,详细解析了Loadpull模板从初始化配置到结果解读的全过程。文章重点阐述了如何根据设计目标灵活设置扫描圆、采样点等关键参数,以解决仿真不收敛、结果不完整等常见问题,并指导读者在功率与效率之间做出理性权衡,最终提取出用于匹配网络设计的最优负载阻抗。

weixin_29234423的博客 598

MOOS-ivp实战:从零搭建水下机器人通信系统(Ubuntu 22.04版)

本文详细介绍了在Ubuntu 22.04系统上从零开始搭建MOOS-ivp水下机器人通信系统的完整实战流程。内容涵盖环境准备、核心安装、MOOSDB通信模型解析、自定义应用节点开发、以及调试监控工具链的使用,旨在帮助开发者快速掌握这一分布式机器人系统框架,构建稳定可靠的水下机器人通信与控制系统。

snow3的博客 636

扒一扒 ReentrantLock 以及 AQS 实现原理

提到JAVA加锁,我们通常会想到synchronized关键字或者是Java Concurrent Util(后面简称JCU)包下面的Lock,今天就来扒一扒Lock是如何实现的,比如我们可以先提出一些问题:当我们通实例化一个ReentrantLock并且调用它的lock或unlock的时候,这其中发生了什么?如果多个线程同时对同一个锁实例进行lock或unlcok操作,这其中又发生了什么?

KimZing的博客 1048

maxwell 平面变压器仿真(一)

在学习开关电源设计的时候,我们难免要设计变压器,采用有限元仿真软件MAXWELL 可以帮助我们确定变压器的励磁电感,漏感等参数。对于我们的理论分析大有裨益。但是苦于这破软件的教程真的是相当的零散,我相信大家用起来也总是苦于没有系统的教程指导,撰写本文的目的有两个,一个是记录自己使用的一些问题,一个是给大家提供一个可以参考的文档。

qq_45405656的博客 8252

从ReentrantLock的实现看AQS的原理及应用

总第374篇2019年 第52篇AQS作为JUC中构建锁或者其他同步组件的基础框架,应用范围十分广泛,这篇文章会带着大家从可重入锁一点点揭开AQS的神秘面纱。前言Java中的大部分同步类...

美团技术团队 8484

S32DS 3.5.8离线包怎么用?保姆级教程教你手动安装S32K3开发环境(附资源下载)

本文详细介绍了S32DS 3.5.8离线包的安装方法,适用于S32K3开发环境的手动搭建。从资源获取、完整性验证到分步安装指南,提供了全面的离线部署解决方案,特别适合军工/车企内网开发等场景。文章还包含版本选择建议、常见问题排查及团队协作方案,帮助开发者高效完成环境配置。

weixin_30471561的博客 480

基于PLC的茶叶揉捻机自动控制系统设计【附代码】

茶叶揉捻是初茶加工过程中的一道关键工序,通过揉捻可以使鲜茶叶成条、碎茶及叶组织细胞破损等。影响茶叶成条率、碎茶率和叶组织细胞破损的主要因素包括揉捻时间、压力和揉捻桶转速。为了提高茶叶品质的稳定性和减轻工人的劳动强度,本文提出了一种基于PLC自动控制技术的茶叶揉捻机控制系统设计。📊 PLC自动化设计 | 毕业设计指导 | 工业自动化解决方案。✅ 具体问题可以私信或查看文章底部二维码。✅ 感恩科研路上每一位志同道合的伙伴!

lagougongzuoshi的博客 1344

AQS与ReentrantLock原理

AQS与ReentrantLock原理

howard1209a的博客 2170

GPT-5.5 是真好用!SCI论文润色与学术写作能力上全面提升,全流程指令已整理好!

输出规范:先输出完整的摘要正文,不添加额外说明,以Markdown表格形式提供中文自检说明,表格包含两列,列标题为“检查项”和“说明”,逐项说明是否已覆盖背景、研究问题、方法、结果及贡献,并简要评价摘要结构与表达是否符合要求,除上述内容外不输出其他信息。:你是一位(学术写作专家/期刊审稿人/论文评审专家),精通学术写作规范、逻辑结构、语法准确性及学术表达方式,你的任务是帮助提升论文的质量,包括语言润色、语法检查、逻辑优化和降低重复率。语言需简洁、正式、具有概括性,不展开具体论述,仅提供结构与要点说明。

智能AI让学术科研更容易 289

Java之Reentrantlock的实现及AQS的原理和应用

ReentrantLock意思为可重入锁,指的是一个线程能够对一个临界资源重复加锁。

qq_62592925的博客 1450

YOLOv11架构革新:华为VanillaNet与BiFPN深度融合的突破性改进实战指南

购买即可解锁300+YOLO优化文章,并且还有海量深度学习复现项目,价格仅需两杯奶茶的钱,别人有的本专栏也有!

LXY_LOVE36的博客 136

lammps不同晶面建模方法汇总

Lammps lattice命令中的orient关键词可实现晶体的旋转和重定向,下面的命令中,111面的法线方向与y正方向重合,说明111面垂直于y轴。在有些模拟中,需要研究特定面的性质,比如研究110面,默认状态下,110面不是坐标平面,研究起来不方便,需要对模型进行旋转,如下图所示。经过旋转后,110面的法线方向与x轴正方向重合,旋转之后再重新对晶体进行切割,新模型的x面就是110面。需要注意的是,这种方法需要明确指定x、y、z轴的正方向分别对应哪三个面的法线方向,缺一不可。大家好,我是小马老师。

lammps_jiayou的博客 358

详解AQS以及ReentrantLock原理

本文将针对AQS原理进行讲解,通过自定义一个不可重入锁的例子以及队ReentrantLock源码的剖析加深对AQS的理解

weixin_53216033的博客 1170

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

轻松的通过ReentrantLock掌握AQS的核心原理

从一次"线程池卡死导致应用假死"的线上故障出发,通过ReentrantLock的使用案例反推AQS的核心原理。深度剖析AQS的state变量、CLH队列、独占模式与共享模式,配合手写100行代码实现简易版ReentrantLock,揭秘为什么ReentrantLock比synchronized更灵活、公平锁与非公平锁的性能差异、以及Condition条件队列的实现原理。图解入队出队流程,给出并发工具类的最佳实践。

比较是偷走幸福的小偷 4165

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

ReentrantLock的底层实现——AQS实现原理

以下文章参考于程序员cxuan 概述 谈到多线程并发编程,我们就逃不掉AQS(AbstractQueuedSynchronizer),所谓的AQS即是抽象的队列式的同步器,内部定义了很多锁相关的方法,我们熟知的ReentrantLock、ReentrantReadWriteLock、CountDownLatch、Semaphore等都是基于AQS来实现的。 ...

qq_45725126的博客 1419

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

上一篇: Nacos 和 Apollo中的 长轮询 定时机制,太好用了~
下一篇: 五张图带你彻底理解 RocketMQ 轨迹消息
JavaShark
博客等级 码龄4年 184粉丝 438原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值