AQS详解2-体系架构介绍

本文详细介绍了AQS(AbstractQueuedSynchronizer)的核心机制,包括其在ReentrantLock中的应用。AQS通过一个volatile同步状态(state)和Node节点构成的双端队列来管理线程的同步。state表示锁的状态,0为空闲,非0表示锁定。Node节点则代表等待的线程,其waitStatus字段指示线程等待状态。AQS的这种设计实现了公平锁和非公平锁的管理,形成了一个高效的同步机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AQS体系架构.

如果还有小伙伴对AQS的基础理论知识不太了解的话,可以先看这篇文章:
AQS详解1:理论介绍

以ReentrantLock中使用为例:
在这里插入图片描述
可以看到不论是公平锁还是非公平锁其实都依赖于AQS.
再看一下AQS的自身.
在这里插入图片描述
主要有一个volatile修饰的同步状态(state)和Node节点,头指针(head),尾指针(tail).
变量理解:
   1.state: 可以理解为我们去银行办理业务时,银行受理窗口的状态,零就是没人,现在可以办理业务,1就是现在正在忙,需要等待.其实也就是当前锁的状态,零就是空闲状态,没有被线程占有.
   2.Node: 银行等候区的顾客.也就是正在阻塞的线程.
这里的Node是一个内部类,有自己的前后指针,加上AQS中的头尾指针,就是一个双端队列的结构,所以一般也说AQS就是state+CLH双端队列.

内部类Node:
在这里插入图片描述
属性解释:
主要看线程的模式:sharde和exclusive 、状态即可:waitStatus
在这里插入图片描述
   这里要注意一下,内部类Node节点中有一个waitStatus,指的是线程的状态,而AQS类中的status,指的是锁的状态.

   其实总结一下也就是这张图:在这里插入图片描述

### Java AQS 工作原理及使用详解 #### 一、AQS 的基本概念 AbstractQueuedSynchronizer (简称 AQS),是一个用于构建锁和其他同步器的基础框架。它通过一个 `int` 类型的状态 (`state`) 来表示资源的共享情况,并提供了一种 FIFO 队列来管理线程之间的竞争。 - **核心字段**: AQS 使用了一个名为 `state` 的整数变量来记录同步状态,该变量可以通过原子方式更新以确保线程安全[^2]。 - **队列模型**: 当多个线程争夺同一个资源时,未能获得资源的线程会被加入到 CLH(Craig, Landin, and Hagersten locks)队列中等待。这种队列是一种双向链表结构,可以有效减少上下文切换带来的开销[^3]。 --- #### 二、AQS 的工作流程 1. **获取锁的过程**: - 调用者尝试获取锁时,如果当前 `state` 允许,则直接获取并修改 `state`;否则进入同步队列排队。 - 如果线程无法立即获取锁,将会被封装成一个节点(Node),并挂载到 CLH 队列中等待唤醒[^4]。 2. **释放锁的过程**: - 当持有锁的线程完成任务后,会调用 `release()` 方法释放锁。 - 此时,AQS 将重新计算 `state` 并通知下一个等待中的线程去尝试获取锁。 3. **条件变量支持**: - AQS 提供了对条件变量的支持,这使得开发者可以在某些特定条件下让线程暂停运行直到满足条件后再继续执行。 - 这部分功能主要由 `ConditionObject` 实现,其中涉及两个独立的队列:一个是主线程的竞争队列,另一个是条件队列[^4]。 --- #### 三、AQS 的两种模式 AQS 支持两种不同的资源共享模式: 1. **独占模式**: - 只能有一个线程占用资源,在大多数情况下对应的是互斥锁的行为。 - JDK 中典型的例子有 ReentrantLock 和 Semaphore(permit=1)。 2. **共享模式**: - 多个线程可以同时访问资源,适用于读写锁场景下允许多个只读操作的情况。 - 如 CountDownLatch 或 CyclicBarrier 所使用的机制就是基于此模式实现的。 --- #### 四、AQS 的典型应用案例 以下是几个常见的基于 AQS 构建的工具类及其用途说明: 1. **ReentrantLock** - 是一种可重入的互斥锁,提供了与 synchronized 关键字类似的锁定行为,同时还增加了更多高级特性,比如公平锁选项以及中断响应能力等。 2. **CountDownLatch** - 允许一个或多个线程一直等到其他一些线程完成一系列操作之后再继续执行。 - 它的核心逻辑在于维护计数,并随着每次 countDown() 减少直至零触发后续动作。 3. **CyclicBarrier** - 让一组线程互相协作到达某个屏障点之前都不能向前推进,非常适合用来解决分阶段处理的任务需求。 4. **Semaphore** - 控制同一时刻最多有多少个线程能够访问某项有限资源集合。 5. **ReadWriteLock** - 区分为读锁和写锁两部分,从而提高并发度——即允许多个读者或者单一作者存在但不允许两者混合发生冲突。 --- #### 五、代码示例 下面给出一段简单的自定义锁实现作为演示如何利用 AQS 创建新的同步组件实例: ```java public class MyMutex extends AbstractQueuedSynchronizer { @Override protected boolean tryAcquire(int acquires) { if (compareAndSetState(0, 1)) { // CAS 操作设置 state setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } @Override protected boolean tryRelease(int releases) { if (getState() == 0) throw new IllegalMonitorStateException(); setExclusiveOwnerThread(null); setState(0); // 清空状态 return true; } public void lock() { acquire(1); } public void unlock() { release(1); } } ``` 上述代码片段展示了怎样借助 AQS 快速搭建起一套基础版的手动控制权限分配方案。 --- ### 总结 通过对 AQS 的学习可以看出其设计精妙之处不仅限于简单地实现了各种类型的锁机构,更重要的是为开发人员提供了一个高度灵活且易于扩展的抽象层面上的操作接口集锦。无论是初学者还是资深工程师都能从中受益匪浅!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员bling

义父,感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值