ReentrantLock实现原理详解

【多线程】轻松彻底搞懂ReentrantLock的底层实现原理 上篇博客讲解了Sychronized的底层实现原理,它是基于jdk实现的,现在此篇博客讲解基于AQS 框架实现的另一个锁ReentrantLock。 阅读详情

ReentrantLock是Java并发包中用于实现可重入锁的类,基于AQS(AbstractQueuedSynchronizer,抽象队列同步器)实现,支持公平锁和非公平锁。

  1. 类结构与AQS基础:ReentrantLock内部有Sync、FairSync和NonFairSync三个内部类。Sync继承自AQS,是公平锁和非公平锁的抽象父类;FairSync和NonFairSync分别实现公平锁和非公平锁。AQS是构建锁和同步器的框架,维护一个FIFO等待队列来管理等待获取资源的线程,通过一个volatile修饰的int类型变量state表示同步状态。不同同步器中,state含义不同,在ReentrantLock中,state表示锁被同一个线程重复获取的次数,0代表未锁定,大于0表示已锁定,数值为获取次数。
  2. 加锁流程
    • 非公平锁加锁:创建ReentrantLock时若不传入参数,默认使用非公平锁(NonFairSync) 。调用lock()方法时,先通过CAS操作尝试将AQS中的同步状态state从0修改为1。若修改成功,将当前线程设置为锁的独占所有者;若失败,调用AQS的acquire(1)方法。acquire(1)方法中,再次调用tryAcquire(1)尝试获取锁(实际调用NonFairSync的nonfairTryAcquire方法 ),该方法先检查state是否为0,是则尝试用CAS将state设为1并设置当前线程为锁的所有者;若state不为0且当前线程是锁的持有者,则将state值增加1,体现可重入特性;若都不满足则返回false。当tryAcquire返回false,执行acquireQueued方法,将当前线程封装成Node节点加入AQS等待队列,然后进入自旋尝试获取锁。若当前节点的前驱节点是头节点且能成功获取锁,则将当前节点设为头节点;否则根据前驱节点的waitStatus值判断是否挂起当前线程。
    • 公平锁加锁:公平锁(FairSync)的lock()方法直接调用AQS的acquire(1)方法。在tryAcquire方法中,除了检查state状态,还会调用hasQueuedPredecessors()方法检查等待队列中是否有其他线程在排队。只有等待队列中没有前驱节点(即没有其他线程先于当前线程等待获取锁),并且能通过CAS操作将state从0修改为1时,当前线程才能获取到锁;否则线程会被加入到等待队列。这确保了线程获取锁的顺序是按照在队列中的等待顺序,实现公平性。
  3. 解锁流程:解锁时调用unlock()方法,实际调用AQS的release(1)方法。release(1)方法内部先调用tryRelease(1)尝试释放锁(在ReentrantLock的Sync类中实现 ),检查当前线程是否是持有锁的线程,若是则将state值减1。当state值变为0时,代表锁已完全释放,将持有锁的线程清空,并返回true。若tryRelease返回true,AQS会调用unparkSuccessor方法唤醒等待队列中的下一个线程(通过LockSupport.unpark()操作 )。
  4. 可重入的实现:由于ReentrantLock是可重入锁,同一线程可多次获取同一把锁。当已持有锁的线程再次调用lock()方法时,会识别出当前线程是锁的持有者,然后将AQS中的state值加1。释放锁时,每次unlock()操作会将state值减1,直到state值为0时,才真正释放锁。这一机制通过在tryAcquire和tryRelease方法中对state值的增减操作实现,保证了同一线程多次获取锁时不会被阻塞。
  5. 公平锁与非公平锁区别
    • 公平锁:在获取锁时,会检查等待队列中是否有其他线程在排队,只有当前线程是等待队列中第一个请求锁的线程时,才会尝试获取锁,确保了线程获取锁的公平性。但由于需要频繁检查队列,上下文切换开销较大,在高并发场景下性能相对较低。
    • 非公平锁:获取锁时先通过CAS尝试获取,不考虑等待队列中的线程。若获取失败,再进入等待队列。这种方式可能会使新线程“插队”获取锁,导致等待队列中的线程等待时间延长,但减少了线程挂起和唤醒的开销,在高并发场景下性能更好。ReentrantLock默认使用非公平锁,因为多数场景下性能更为重要。
JAVA多线程详解(三):ReentrantLock实现原理与源码分析 刚学java的多线程通信时,往往只能知道在多线程访问共享资源时加上锁,保证多线程访问共享资源时的同步操作。利用ReentrantLock的lock()方法加锁,利用ReentrantLock的unlock()方法释放锁。那么加锁和释放锁的内部是怎么实现的呢?其源码解释的比较清晰。下面将从源码的整体架构和具体细节来分析ReentraLock的实现原理。由于大量使用了CAS操作,先介绍CAS的实现原理... 阅读详情

相关推荐

W5500 MACRAW模式实战:在ESP32上抓取并解析原始以太网数据包

本文详细介绍了如何在ESP32开发板上使用W5500芯片的MACRAW模式捕获和解析原始以太网数据包。通过硬件连接指南、代码实现示例和协议解析技巧,帮助开发者深入理解网络通信底层机制,实现网络嗅探和自定义协议开发等高级应用。

weixin_42520573的博客 418

8. 共享模型之工具-J.U.C工具包-ReentrantLock 原理

AQS 原理 1. 概述 全称是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架 特点: 用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁 getState - 获取 state 状态 setState - 设置 state 状态 compareAndSetState - cas 机制设置 state 状态 独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源 提供了基于 F

liuhehe的博客 529

四、嘉立创EDA原理图绘制实战:从零搭建STM32温湿度监测系统

本文详细介绍了使用嘉立创EDA标准版从零开始绘制STM32温湿度监测系统原理图的完整流程。涵盖核心元器件选型、电源电路设计、ADC按键创新应用及模块化布局技巧,帮助电子爱好者快速掌握STM32系统设计,提升嵌入式开发实战能力。

h0i1j2k3l的博客 883

ReentrantLock原理及详细的使用方法

的核心是基于AQS(抽象队列同步器)实现的。AQS 维护了一个队列,用于管理所有请求锁的线程。每个线程尝试获取锁时,如果当前锁被其他线程持有,则进入等待队列,阻塞等待锁释放。一旦锁释放,AQS 会从队列中唤醒下一个线程,允许它获取锁。提供了比更灵活的锁控制方式。选择公平锁和非公平锁;提供尝试获取锁和可中断的锁;允许锁的重入;支持手动加锁和解锁的细粒度控制。

yymagicer的博客 2345

NC数据预处理避坑指南:从MATLAB读取到GeoTIFF导出,解决坐标翻转与值域异常

本文详细解析了NC数据预处理中的常见问题,包括MATLAB读取时的坐标翻转与GeoTIFF导出时的值域异常。通过实战案例,介绍了如何解决矩阵方向错乱、处理FillValue与scale_factor、精准移植空间参考等关键问题,帮助研究者高效完成气象数据的批量处理与GIS兼容性验证。

weixin_30788619的博客 653

条件DDPM:Diffusion model的第三个巅峰之作

前言:DDPM从2020年诞生,短短一年的时间,模型上有两个巨大的改进,其中一个就是condition的引入,最近大部分DDPM相关的论文都会讨论这一点,有些文章称之为latent variable。和当年GAN的发展类似,CGAN和DCGAN的出现极大程度上促进了GAN的发扬光大,意义重大。本文基于前面几篇文章继续聊一聊: 从VAE到Diffusion Model_沉迷单车的追风少年-优快云博客 为什么diffusion model扩散模型可以称为score-based models?_沉迷单车的.

沉迷单车的追风少年 1万+

重点,一文掌握ReentrantLock加解锁原理!|原创

本文详细讲解了 ReentrantLock 加锁和释放锁的原理,以及和 Synchronized 的对比。本文较长,建议收藏!点击上方“后端开发技术”,选择“设为星标” ,优质资源及时送达简要总结 ReentrantLock实现原理:volatile 变量 + CAS设置值 + AQS + 两个队列实现阻塞:同步队列 + CAS抢占标记为 valatile 的 state实现等待唤醒:await ...

Daniel的博客 1011

Allegro172版本如何在联机模式下使用skill文件操作指导

注意:如果下次重新开启Symphony模式的时候可能导致symphony_skill中的文件内容被清空,所以最好将自己常用的skill文件都写到symphony_skill.txt中去,然后做好备份,需要的时候,在开启软件后把文件放到env目录中去。在用Allegeo172版本进行PCB设计的时候,有时会用到Symphony模式进行多人实时在线协同设计,如下图。这个模式设计起来可以提升设计速度,但是也有一个缺陷,就是不能使用skill文件。如下图,当调用skill的时候就会出现如下报错。

weixin_54787054的博客 1586

Java线程并发中的锁——ReentrantLock(重入锁)原理详解

ReentrantLock是一个重入锁,可以支持一个线程对资源重复加锁,他还支持公平加锁和非公平加锁。synchronized关键字也隐式的支持重进入,比如一个synchronized修饰的递归方法,在方法执行时,执行线程在获取了锁之后仍能连续多次地获得该锁ReentrantLock虽然没能像synchronized关键字一样支持隐式的重进入,但是在调用lock()方法时,已经获取到锁的线程,能够再

路漫漫,水迢迢 9015

AI系统架构原理与代码实战案例讲解

人工智能的概念可以追溯到上世纪50年代,图灵测试的提出标志着人工智能作为一门学科的诞生。早期的研究主要集中在符号推理、专家系统等领域,取得了一些突破,例如机器定理证明、西洋跳棋程序等。上世纪80年代,随着专家系统的兴起,人工智能进入了一个黄金时期。专家系统通过模拟人类专家的知识和经验进行推理和决策,在医疗诊断、故障诊断等领域取得了成功应用。进入90年代,由于计算能力的限制和数据量的不足,人工智能的发展陷入低谷。近年来,随着深度学习技术的突破、大数据的兴起以及计算能力的提升,人工智能迎来了第三次发展浪潮,在图

AI天才研究院 1793

Xilinx差分原语-IBUFGDS与OBUFGDS FPGA

它将差分信号转换为单端信号,并将其输入到FPGA的逻辑片上。它将单端信号转换为差分信号,并将其输出到FPGA的引脚。在FPGA设计中,差分信号是一种常见的信号传输方式,用于提高抗噪性和抑制共模噪声。Xilinx是一家知名的FPGA供应商,提供了许多差分原语,其中包括IBUFGDS和OBUFGDS。通过使用Xilinx的差分原语,如IBUFGDS和OBUFGDS,可以实现差分信号的输入和输出。这些差分原语提供了方便且可靠的接口,使得在FPGA设计中处理差分信号变得更加简单和高效。是差分输入信号的端口,

git_database727的博客 2096

简单实现ReentrantLock,详解ReentrantLock底层原理

AbstractQueuedSynchronizer类不止服务于ReentrantLock类,因此该类里面有很多跟ReentrantLock不想关的代码存在,本文将提取ReentrantLock类和AbstractQueuedSynchronizer类的核心代码进行解释说明。本文末尾将附带经过我提取的手写的ReentrantLock代码,代码上附有我对该锁的理解的注解。的核心就是类,要了解就要先了解一、AbstractQueuedSynchronizer类。

duan614的博客 1897

【AI编程】Claude Code 最强AI 编程利器项目实战详解

Claude Code 最强AI 编程利器项目实战详解

congge 7397

ReentrantLock 实现原理详解

u013332124的专栏 639

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

详解synchronized 和ReentrantLock两种锁实现原理

概述 Java 中的并发锁大致分为隐式锁和显式锁两种。隐式锁就是我们最常使用的 synchronized 关键字,显式锁主要包含两个接口:Lock 和 ReadWriteLock,主要实现类分别为ReentrantLock 和 ReentrantReadWriteLock,这两个类都是基于AQS(AbstractQueuedSynchronizer) 实现的。还有的地方将CAS也称为一种锁,...

ly199108171231的博客 4502

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

【Java第80集】java ReentrantLock底层实现原理详解

的核心实现依赖于 AQS,它是 Java 并发包中的基础框架,用于构建锁和同步器。state 变量表示锁的状态。state = 0:锁未被占用。state > 0:锁被占用,数值表示重入次数。等待队列(CLH 队列):维护等待锁的线程队列,遵循 FIFO 原则(公平锁)或允许插队(非公平锁)。的底层实现基于 AQS 框架,通过state变量管理锁状态,结合 CLH 队列实现线程排队。可重入性:通过 state 计数器实现。公平性选择:支持公平锁和非公平锁。高级功能。

学不可以已,活到老,学到老。 812

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Java中synchronized和ReentrantLock锁的实现原理详解

维度OS层面相同(最终都是futex)相同(最终都是futex)用户态优化锁升级(偏向/轻量级/重量级)AQS队列+CAS自旋公平性非公平(实现决定)可选择功能基础丰富(可中断、超时、条件等)性能低竞争时更优高竞争时可能更优核心结论两者的操作系统底层机制本质相同,都是基于互斥锁和条件变量性能差异主要来自用户态的实现策略(锁升级 vs AQS)更适合简单场景,依赖JVM优化提供更多控制和可预测性这解释了为什么在低竞争时可能更快(得益于锁升级),而在高竞争时。

学亮编程手记 606

Java 并发编程进阶:ReentrantLock 实现原理详解

在 Java 并发编程中,最常见的加锁方式莫过于 synchronizedsynchronized 使用简单,并且由 JVM 保证锁的获取与释放,是 Java 中最基础的线程同步机制不过随着并发场景越来越复杂,synchronized 的局限性也逐渐显现出来:无法尝试获取锁无法设置获取锁超时时间无法中断等待锁的线程不支持公平锁只能使用单一条件队列。

m0_71751187的博客 408

【并发编程】详解 ReentrantLock:深入剖析 AQS 支撑下的可重入锁机制与实现原理

【并发编程】详解 ReentrantLock:深入剖析 AQS 支撑下的可重入锁机制与实现原理

赵士杰——成功并非一蹴而就,而是在持之以恒的努力中逐渐实现。 3363

JAVA多线程系列--ReentrantLock实现原理-AQS详解

1.概述  前文笔者已经讲了ReentrantLock的使用,在这篇文章中我们将讲讲ReentrantLock的底层实现AbstractQueuedSynchronized(AQS)。   AQS:抽象的队列式的同步器。AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock/Semaphore/CountDownLatch。2.AQS框架

niyuelin1990的博客 624

如何应对Android面试官->AQS原理和volatile详解,手写ReentrantLock核心实现

AbstractQueuedSynchronizer,JDK提供的一个抽象类;这些全是 AbstractQueuedSynchronizer 的子类;AbstractQueuedSynchronizer 是 JDK 中用来构建同步并发的基础组件;AQS 中有一个比较重要的同步变量:private volatile int state // 同步状态;不管是 JDK 还是我们自己,在实现一个同步类的时候,都要围绕着这个 state 来做文章,修改它的值来表示当前的同步状态发生了变化;

IT_Android的博客 1049

ReentrantLock 源码分析

java.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这些行为的抽象就是基于AbstractQueuedSynchronizer(简称AQS)实现的,AQS是一个抽象同步框架,可以用来实现一个依赖状态的同步器。JDK中提供的大多数的同步器如Lock, Latch, Barrier等,都是基于AQS框架来实现的一般是通过一个内部类Sync继承 AQS将同步器所有调用都映射到Sync对应的方法。

weixin_39165055的博客 1256

ReentrantLock实现原理与使用风险

ReentrantLock 提供了比 synchronized 更灵活的锁机制,但同时也带来了更大的复杂性和责任。正确管理锁的生命周期- 确保在 finally 块中释放锁避免死锁- 使用超时机制和统一的锁获取顺序合理选择公平性- 非公平锁性能更好,公平锁避免饥饿控制锁粒度- 保持临界区代码简短考虑性能影响- 在高度竞争的场景下评估性能需求正确使用 ReentrantLock 可以构建高效、可靠的并发程序,但需要开发者对并发编程有深入的理解。

weixin_46322148的博客 424

ReentrantLock源码分析

  前言      之前这篇关于AQS的源码分析的文章:AbstractQueuedSynchronizer&CountDownLatch源码分析 不够详细,这篇文章再次从ReentrantLock出发来深入分析AQS的源码。可以先看看之前那篇文章大概了解一下AQS,再来看这篇文章。      ReentrantLock加锁过程      ReentrantLock默认使用非公平锁,这里先...

li123128的博客 157

ReentrantLock 原理

循环,找出当前节点的前驱节点定义为p,此时p就是哑元节点,此时 p == head,再次尝试获取锁(如果当前节点是排在第二位的节点,就可以尝试再次加锁),如果尝试加锁成功。先将当前节点的状态设置为0,进入enq(node)方法,将node挂在到阻塞队列末尾,返回node的前驱节点(Thread-3)记为p,将p的状态设置为-1,然后返回true。将关联s线程(刚才关联Thread-1线程的节点)的节点设置为头节点(删除之前的头节点,将此节点关联的线程改为null)

一+一加1的博客 2059
上一篇: 进程同步和线程的同步
下一篇: AQS原理详解
java烤冷面
博客等级 码龄4年 177粉丝 29原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值