首页 > 其他分享 >AQS原理

AQS原理

时间:2024-07-06 16:20:43浏览次数:16  
标签:加锁 AQS 队列 ReentrantLock state 线程 原理

AQS

1.引言

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

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

image-20240705212240518

一个Lock对象,然后加锁和释放锁

你这时可能会问,这个跟AQS有啥关系?

关系大了去了!因为java并发包下很多API都是基于AQS来实现的加锁和释放锁等功能的,AQS是java并发包的基础类

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

那么AQS的全称是什么呢?

2. AbstractQueuedSynchronizer

给大家画一个图,看一下ReentrantLock和AQS之间的关系

image-20240705212248663

我们看上图,说白了,ReentrantLock内部包含了一个AQS对象,也就是AbstractQueuedSynchronizer类型的对象

这个AQS对象就是ReentrantLock可以实现加锁和释放锁的关键性的核心组件

3.ReentrantLock加锁和释放锁的原理

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

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

初始状态下,这个state的值是0

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

image-20240705212256896

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

(关于CAS,之前专门有文章做过详细阐述,大家可以自行阅读了解)

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

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

image-20240705212302658

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

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

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

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

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

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

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

4. 我们来看看锁的互斥是如何实现的?

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

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

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

image-20240705212308922

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

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

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

image-20240705212314192

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

整个过程,参见下图:

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

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

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

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

image-20240705212319069

5. 总结

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

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

其实一句话总结:AQS就是一个并发包的基础组件,用来实现各种锁,各种同步组件的

它包含了state变量、加锁线程、等待队列等并发中的核心组件

6. 纠正

  1. 看了一下jdk 1.8的源码,线程2并不会尝试进行CAS,完整表述是:如果发现状态不对(state != 0),就检查当前独占线程是否为自己,如果是则直接修改state并返回true,否则则返回false

  2. 还有就是,应该里面维护两个队列。一个是有限数量的等待队列;还有一个是数量无限制的阻塞队列,等待队列满了以后再有并发的线程过来,就会放到阻塞队列中阻塞起来,从而防止运行的线程过多而引起的CPU资源占用过大的问题

标签:加锁,AQS,队列,ReentrantLock,state,线程,原理
From: https://www.cnblogs.com/zhangyf1121/p/18287390

相关文章

  • 【SpringBoot】SpringBoot自动装配原理
    在上一篇文章中,讲述了SpringBoot核心启动流程源码解析其中,主要是构造方法和run方法的处理,本篇接着准备上下文环境后续,讲述是如何将springboot是如何完成自动装配,主线其实就是什么时候完成对主类的加载,也即对SpringBootApplication类加载到IOC容器中什么时候完成对Spring......
  • 【C/C++ new/delete和malloc/free的异同及原理】
    new/delete和malloc/free都是用于在C++(以及C语言在malloc/free的情况下)中动态申请和释放内存的机制,但它们之间存在一些显著的异同点。以下是对这两组函数/运算符的异同点的详细分析:相同点目的相同:两者都用于在堆(heap)上动态地分配和释放内存。手动管理:无论是new/delete还是......
  • 计算机组成原理复习与预习指南~持续更新~
    计算机组成原理是计算机科学领域的基石,理解它不仅能帮助你更好地掌握计算机的工作原理,还能为你在编程、系统设计和性能优化方面提供强大的理论支持。本文将带你深入探索计算机的组成,从CPU、存储器到系统总线和I/O系统,全面解析各个部分的工作原理和实际应用。同时,我们也会结......
  • 数据库原理之并发控制的基本概念
    我们今天继续来看数据库原理,我们简单讲讲数据库的并发控制。并发控制的定义并发控制是为了保证事务的隔离性和一致性,数据库管理系统需要对并发操作进行正确调度。并发控制的主要技术有:、时间戳、乐观控制法、多版本并发控制等。并发操作带来的数据不一致性主要有以下三点:......
  • 天气学原理复习整理(南信大)
    第0章绪论天气学的含义:天气学原理是研究不同尺度的天气系统和天气现象发生发展及其变化的基本规律,并利用这些规律来预测未来天气的科学。天气系统:在时间或者空间上可以与其他系统区别开来的一个实体。在系统与系统之间存在着界面,而各系统的物理量可以通过界面交换。天气过......
  • 每天一道Java面试题系列之--Spring事务的实现原理
    面试题描述Spring事务的实现原理,并解释以下概念:PlatformTransactionManager 接口的作用是什么?什么是事务的传播行为?声明式事务和编程式事务有什么区别?@Transactional 注解是如何工作的?题解1. PlatformTransactionManager 接口PlatformTransactionManager是Spring事务......
  • 站在架构师角度:深入剖析Spring事务管理底层原理
    摘要Spring框架的事务管理是企业级应用开发中的一个核心特性,它为不同的事务使用场景提供了统一的抽象和实现。本文从架构师的角度出发,深入探讨Spring事务管理的底层原理,包括其设计哲学、核心组件、以及事务传播行为等。1.事务管理概述事务是数据库操作中的一个基本概念,它保......
  • springboot 自动配置原理
    @SpringBootApplication发现是一个复合注解@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan由三个注解组合而来@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@SpringBootConfiguration@EnableAutoConfigurat......
  • 417、基于51单片机的热水器(燃气,温度,LCD1602,阀门PID)(程序+Proteus仿真+原理图+流程图+
    毕设帮助、开题指导、技术解答(有偿)见文未目录方案选择单片机的选择显示器选择方案一、设计功能二、Proteus仿真图单片机模块设计三、原理图四、程序源码资料包括:需要完整的资料可以点击下面的名片加下我,找我要资源压缩包的百度网盘下载地址及提取码。方案选择......
  • 【0294】Postgres内核 dynahash 之 hash_search 实现原理
    相关文章:【0289】Postgres内核之哈希表(HashTables)【0290】Postgres内核之dynahash(动态哈希表,dynamichashtables)(概念篇)【0291】Postgres内核之dynahashtable创建【0292】Postgres内核源码之dynahash插入entry实现【0293】Postgres内核之创建dynahashtable解惑......