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

相关推荐
Z_z在努力2 分钟前
【杂类】Spring 自动装配原理
java·spring·mybatis
老赵的博客3 分钟前
c++ 杂记
开发语言·c++
jimmy.hua6 分钟前
[C++刷怪笼]:set/map--优质且易操作的容器
开发语言·c++
程序员爱钓鱼14 分钟前
Go语言实战案例-开发一个Markdown转HTML工具
前端·后端·go
小小菜鸡ing30 分钟前
pymysql
java·服务器·数据库
getapi32 分钟前
shareId 的产生与传递链路
java
桦说编程42 分钟前
爆赞!完全认同!《软件设计的哲学》这本书深得我心
后端
thinktik1 小时前
还在手把手教AI写代码么? 让你的AWS Kiro AI IDE直接读飞书需求文档给你打工吧!
后端·serverless·aws
w2sfot1 小时前
Passing Arguments as an Object in JavaScript
开发语言·javascript·ecmascript