谈谈你对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节点),而不是头节点本身。 因为头节点通常是已经成功获取同步状态(如锁)的线程。这个线程正在执行它的临界区代码。

相关推荐
上去我就QWER7 小时前
Qt中如何获取系统版本信息
开发语言·qt
我是苏苏8 小时前
C#高级:程序查询写法性能优化提升策略(附带Gzip算法示例)
开发语言·算法·c#
木木子99998 小时前
业务架构、应用架构、数据架构、技术架构
java·开发语言·架构
qq_54702617910 小时前
Flowable 工作流引擎
java·服务器·前端
鼓掌MVP11 小时前
Java框架的发展历程体现了软件工程思想的持续进化
java·spring·架构
编程爱好者熊浪11 小时前
两次连接池泄露的BUG
java·数据库
lllsure11 小时前
【Spring Cloud】Spring Cloud Config
java·spring·spring cloud
鬼火儿12 小时前
SpringBoot】Spring Boot 项目的打包配置
java·后端
NON-JUDGMENTAL12 小时前
Tomcat 新手避坑指南:环境配置 + 启动问题 + 乱码解决全流程
java·tomcat
cr7xin12 小时前
缓存三大问题及解决方案
redis·后端·缓存