谈谈你对AQS的理解

AQS概述

AQS,全称为AbstractQueuedSynchronizer,是Java并发包(java.util.concurrent)中一个核心的框架,主要用于构建阻塞式锁和相关的同步器,也是构建锁或者其他同步组件的基础框架。AQS提供了一种基于FIFO(First-In-First-Out)的CLH(三个人名缩写)双向队列的机制,来实现各种同步器,如ReentrantLock、Semaphore、CountDownLatch等。

AQS与Synchronized的区别

|------------------|---------------------|
| synchronized | AQS |
| 关键字,c++ 语言实现 | java 语言实现 |
| 悲观锁,自动释放锁 | 悲观锁,手动开启和关闭 |
| 锁竞争激烈都是重量级锁,性能差 | 锁竞争激烈的情况下,提供了多种解决方案 |

AQS常见的实现类

  • ReentrantLock 阻塞式锁
  • Semaphore 信号量
  • CountDownLatch 倒计时锁

独占锁与共享锁

AQS 根据资源互斥级别提供了两种资源访问模式:独占锁 (exclusive)和共享锁 (shared)。独占锁一次只允许一个线程持有,如ReentrantLock。共享锁允许多个线程同时访问,如Semaphore和ReadWriteLock的读锁。同时其定义Condition结构提供了wait/signal等待唤醒机制。

原理概述

AQS维护了一个volatile int state变量和一个先进先出的CLH双向队列( 也叫等待队列,其中CLH为这个队列的三个发明者人名的缩写),队列中的节点Node持有线程引用,每个节点均可通过getState()、setState()和compareAndSetState()对state进行修改和访问。

state变量值用来表示锁的状态,0表示无锁,1表示有锁。

Node 节点包含线程的引用和节点的状态信息。

当线程获取锁时,即试图对state变量做修改,如修改成功则获取锁;如修改失败则包装为节点添加到双向队列中,等待持有锁的线程释放锁并唤醒双向队列中的节点。

工作机制

只有一个线程争抢 资源

当第一个线程0进入并通过CAS操作成功修改state值(即成功获取了锁或其他同步状态),此时该线程不会被封装成Node节点放到**CLH双向队列(等待队列)**中。

当第一个线程成功获取锁,此时来了2个线程,分别是线程1和线程2,它们想要获取锁,此时线程0还未释放锁,它们经过CAS操作后都获取锁失败,线程1和线程2就会被封装成Node节点并加入CLH双向队列(等待队列) 中进行排队,直到线程0释放锁后被唤醒,被唤醒的线程可以重新尝试获取锁。

如果多个线程共同去抢这个资源是如何保证原子性的呢?

当多个线程共同去修改state状态的时候,使用CAS自旋锁来保证原子性,确保只能有一个线程修改成功,修改失败的线程将会进入**CLH双向队列(等待队列)**中进行排队等待

AQS是公平锁吗,还是非公平锁?

  • 新的线程与队列中的线程共同来抢资源,是非公平锁
  • 新的线程到队列中等待,只让队列中的head线程获取锁,是公平锁

排队机制

**CLH双向队列(等待队列)**中Node节点的排队机制为:当队列为空时则使用尾插法向队列插入一个个使用线程封装好的Node节点,如果队列不为空,就向当前队列的尾部插入节点。总的来说还是使用尾插法插入Node节点

唤醒机制

AQS(AbstractQueuedSynchronizer)的唤醒机制中,唤醒的是**CLH双向队列(等待队列)**头节点的后继节点(即头节点的next节点),而不是头节点本身。 因为头节点通常是已经成功获取同步状态(如锁)的线程。这个线程正在执行它的临界区代码。

相关推荐
守护者17011 分钟前
JAVA学习-练习试用Java实现“使用Arrays.toString方法将数组转换为字符串并打印出来”
java·学习
源码哥_博纳软云12 分钟前
JAVA同城服务场馆门店预约系统支持H5小程序APP源码
java·开发语言·微信小程序·小程序·微信公众平台
禾高网络14 分钟前
租赁小程序成品|租赁系统搭建核心功能
java·人工智能·小程序
学会沉淀。20 分钟前
Docker学习
java·开发语言·学习
如若12321 分钟前
对文件内的文件名生成目录,方便查阅
java·前端·python
西猫雷婶1 小时前
python学opencv|读取图像(二十一)使用cv2.circle()绘制圆形进阶
开发语言·python·opencv
kiiila1 小时前
【Qt】对象树(生命周期管理)和字符集(cout打印乱码问题)
开发语言·qt
初晴~1 小时前
【Redis分布式锁】高并发场景下秒杀业务的实现思路(集群模式)
java·数据库·redis·分布式·后端·spring·
盖世英雄酱581361 小时前
InnoDB 的页分裂和页合并
数据库·后端
小_太_阳1 小时前
Scala_【2】变量和数据类型
开发语言·后端·scala·intellij-idea