AQS介绍

AQS,即AbstractQueuedSynchronizer, 队列同步器,它是Java并发用来构建锁和其他同步组件的基础框架。来看下同步组件对AQS的使用:

AQS是一个抽象类,主是是以继承的方式使用。AQS本身是没有实现任何同步接口的,它仅仅只是定义了同步状态的获取和释放的方法来供自定义的同步组件的使用。从图中可以看出,在java的同步组件中,AQS的子类(Sync等)一般是同步组件的静态内部类,即通过组合的方式使用。

抽象的队列式的同步器,AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock/Semaphore/CountDownLatch

它维护了一个volatile int state(代表共享资源)和一个FIFO(双向队列)线程等待队列(多线程争用资源被阻塞时会进入此队列)

AQS原理简介
在这里插入图片描述
AQS的实现依赖内部的同步队列(FIFO双向队列),如果当前线程获取同步状态失败,AQS会将该线程以及等待状态等信息构造成一个Node,将其加入同步队列的尾部,同时阻塞当前线程,当同步状态释放时,唤醒队列的头节点。

上面说的有点抽象,来具体看下,首先来看AQS最主要的三个成员变量:

private transient volatile Node head;

private transient volatile Node tail;

private volatile int state;

上面提到的同步状态就是这个int型的变量state. head和tail分别是同步队列的头结点和尾结点。假设state=0表示同步状态可用(如果用于锁,则表示锁可用),state=1表示同步状态已被占用(锁被占用)。

下面举例说下获取和释放同步状态的过程:
获取同步状态
假设线程A要获取同步状态(这里想象成锁,方便理解),初始状态下state=0,所以线程A可以顺利获取锁,A获取锁后将state置为1。在A没有释放锁期间,线程B也来获取锁,此时因为state=1,表示锁被占用,所以将B的线程信息和等待状态等信息构成出一个Node节点对象,放入同步队列,head和tail分别指向队列的头部和尾部(此时队列中有一个空的Node节点作为头点,head指向这个空节点,空Node的后继节点是B对应的Node节点,tail指向它),同时阻塞线程B(这里的阻塞使用的是LockSupport.park()方法)。后续如果再有线程要获取锁,都会加入队列尾部并阻塞。

释放同步状态
当线程A释放锁时,即将state置为0,此时A会唤醒头节点的后继节点(所谓唤醒,其实是调用LockSupport.unpark(B)方法),即B线程从LockSupport.park()方法返回,此时B发现state已经为0,所以B线程可以顺利获取锁,B获取锁后B的Node节点随之出队。

上面只是简单介绍了AQS获取和释放的大致过程,下面结合AQS和ReentrantLock源码来具体看下JDK是如何实现的,特别要注意JDK是如何保证同步和并发操作的。

<think>好的,我现在需要帮用户解答关于AQS的面试题和知识点。首先,用户提供了几个引用内容,我需要仔细看看这些引用里有什么有用的信息。引用1提到了AQS是什么、核心原理、公平锁和非公平锁的区别,以及非公平锁的加锁解锁流程。引用2说线程池中的Worker基于AQS实现。引用3提到ReentrantLock、CountDownLatch、Semaphore等同步组件基于AQS。引用4提到Semaphore、CountDownLatch等的并发工具。引用5是关于双重检查锁和volatile的,可能和AQS的关系不大,但可能涉及并发知识。 用户的问题是想要了解AQS相关的面试题或知识点,特别是解析Java并发的部分。我需要根据这些引用内容,结合自己的知识,整理出常见的AQS面试题,并给出解析。 首先,AQS是什么?根据引用1和3,AQS是AbstractQueuedSynchronizer,是Java并发包的核心框架,用于构建锁和同步器。它内部使用了一个FIFO队列来管理线程的排队工作,比如获取锁失败的线程会被加入队列中。 接下来,核心原理部分。AQS通过一个int类型的state变量来表示同步状态,比如ReentrantLock中state表示重入次数,Semaphore中表示许可数量。引用1提到AQS的核心是state变量和CLH队列,以及模板方法模式,子类需要实现tryAcquire和tryRelease等方法。 然后是公平锁和非公平锁的区别,引用1提到公平锁严格按照FIFO顺序获取锁,而非公平锁允许插队,可能造成饥饿但吞吐量高。非公平锁的流程可能是在尝试获取锁时直接CAS修改state,失败后再进入队列排队。 需要检查是否有其他常见面试题,比如AQS的应用场景,如ReentrantLock、CountDownLatch、Semaphore等,这些在引用3和4有提到。此外,可能还涉及AQS的模板方法,比如acquire、release等,以及如何自定义同步器。 可能还需要提到AQS的两种模式:独占模式和共享模式。独占模式如ReentrantLock,共享模式如Semaphore和CountDownLatch。引用4中的Semaphore和CountDownLatch属于共享模式,允许多个线程同时执行。 在回答时,要确保使用正确的中文,数学表达式用$...$格式,独立公式用$$...$$。但根据用户的问题,可能数学公式较少,但如果有状态变量的说明,可能需要用行内格式,比如state变量用$state$。 另外,用户可能需要知道AQS中的等待队列是CLH变体,使用双向链表。还有条件变量Condition的实现,每个ConditionObject维护一个等待队列。 需要确保引用来源正确,比如引用1到5,在回答末尾添加引用标识。比如在提到AQS是什么时,引用[^1];在提到ReentrantLock等组件时引用[^3];在共享模式时引用[^4]。 可能的问题点:用户提供的引用5是关于单例模式的双重检查锁和volatile,这可能和AQS关系不大,但可能作为并发的其他知识点出现。但用户的问题集中在AQS,所以可能不需要涉及这部分,除非在相关问题中提到。 生成的相关问题可能包括:AQS的工作原理,如何基于AQS实现自定义锁,AQS的共享模式与独占模式的区别,AQS在哪些并发工具中的应用,公平锁和非公平锁的实现差异等。 需要确保回答结构清晰,分点解答,每个问题点给出解析,并正确引用来源。例如,在解释AQS核心原理时,引用[^1];在应用场景时引用[^4]。 总结下来,回答的结构应该是先介绍AQS的定义和作用,然后分点解析常见面试题,如核心原理、公平锁与非公平锁的区别、应用场景等,最后生成相关问题。需要确保每个部分都有对应的引用支持,并且语言通顺,符合用户要求的中文回答,正确使用LaTeX格式。</think>### AQS 面试题解析(Java 并发) #### 1. **AQS 是什么?** AQS(AbstractQueuedSynchronizer)是 Java 并发包的核心框架,用于构建锁和同步器(如 `ReentrantLock`、`Semaphore`)。它通过一个 **FIFO 队列**管理线程的排队等待,并通过 **`state` 变量**(整型)表示同步状态(如锁的持有次数、信号量许可数)[^1]。 --- #### 2. **AQS 的核心原理** - **`state` 变量**: 表示资源状态,如 `ReentrantLock` 中 `state` 记录锁的重入次数,`Semaphore` 中表示可用许可数。通过 **CAS 操作**保证原子性修改。 - **CLH 队列**: 使用双向链表实现的等待队列,存储竞争资源失败的线程。线程通过 `acquire()` 方法尝试获取资源,失败后加入队列并阻塞;释放资源时唤醒后继线程。 - **模板方法模式**: 子类需实现 `tryAcquire()`(独占模式获取资源)、`tryRelease()`(释放资源)等方法,AQS 负责队列管理和线程阻塞/唤醒。 --- #### 3. **公平锁与非公平锁的区别** - **公平锁**: 严格按照 FIFO 顺序分配锁,保证无饥饿,但吞吐量较低。 实现:在 `tryAcquire()` 中检查队列是否有等待线程,若有则直接失败。 - **非公平锁**: 允许线程“插队”(即使队列中有等待线程,新线程仍可尝试直接获取锁),吞吐量高,但可能导致饥饿。 实现:`ReentrantLock` 默认非公平锁,直接通过 CAS 修改 `state` 竞争资源[^1]。 --- #### 4. **AQS 的应用场景** - **独占模式**: `ReentrantLock`(可重入锁)、`ReentrantReadWriteLock`(读写锁)。 - **共享模式**: `Semaphore`(信号量,控制并发线程数)、`CountDownLatch`(倒计时门闩,等待多个任务完成)。 --- #### 5. **AQS 的线程阻塞与唤醒** - **`LockSupport` 工具类**: AQS 使用 `LockSupport.park()` 阻塞线程,`LockSupport.unpark(thread)` 唤醒线程,底层依赖 `Unsafe` 类实现[^2]。 --- #### 6. **基于 AQS 实现自定义锁** 示例代码框架: ```java public class MyLock extends AbstractQueuedSynchronizer { @Override protected boolean tryAcquire(int arg) { if (compareAndSetState(0, 1)) { // CAS 修改 state setExclusiveOwnerThread(Thread.currentThread()); // 设置持有线程 return true; } return false; } @Override protected boolean tryRelease(int arg) { if (getState() == 0) throw new IllegalMonitorStateException(); setExclusiveOwnerThread(null); setState(0); // 释放锁 return true; } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值