AQS和CAS粗略介绍

1、AQS

是什么:全称 abstractQueuedSynchronizer,一个抽象类,队列同步器。常见的实现有ReentrantLock、ReadWriteLock

有什么用:构建锁、释放锁、同步队列。

怎么实现:

先看AQS中的重要参数:

head:记录队列中头部节点

tail:记录队列中尾部节点

state:记录队列中等待访问线程数量,通过volatile关键字修饰,保证该参数对所有参数可见且有序(就是有序访问,针对于内存上)

note内部类:一个双向队列

thread:当前占用资源线程

好了,下边介绍AQS如何构建锁、释放锁,实现队列同步:

这里首先说一下,AQS采用的是乐观锁,乐观锁其实不是真实的锁,它只是在代码层面通过CAS算法或对比版本号来防止并发,实现锁的作用。

1)当一个线程请求资源时,首先要获取锁资源(也不是实际意义的锁,方便起见,下边说锁时候理解就好),就是通过CAS算法,判断内存上的state值是否为0,即队列中是否有阻塞线程,若没有,可直接将新值赋到内存地址上,然后进行一系列操作(创建note节点,head、tail都指向该note节点,记录当前线程,state加1等操作);若有阻塞队列,也不会直接存入队列,而是会再尝试获取一次锁,这次也获取失败了,那就存入队列。这就实现了加锁过程。

2)当一个线程操作完资源以后,若存在head节点,且head指向节点中的waitState 不为0,则唤醒head指向的节点,将AQS中的state设置为0,head指向的节点中的waitState的值设为0,唤醒head节点对应线程,重新通过CAS算法竞争锁资源。这就是释放锁过程。

通过枷锁、释放锁实现队列同步。

2、CAS

是什么:全称compareAndSwap 顾名思义 比较与计算,它就是一种算法

有什么用:可以实现加锁效果,只是同样的效果,它并不是一种锁,就是能防止并发访问出错

怎么实现:线程请求内存资源,资源不加锁,哪个线程都可以取,取出来爱怎么操作都行,写入内存时再进行比较,就是比较从内存中取出的数据和此时内存中的数据是否一样,如果一样就认为在此期间没有其他线程访问,可安全写入;若数据不一样,则取回新数据,重新操作,然后重新写入内存,当然这时候写入内存时重新比较,若又不一样,表明这期间又被其他线程改了,就再取回再操作再比较,这就是我们所说的子旋,直到一样时写入。

当然了,这里面有个很著名的ABA问题,什么意思呢,就是我第一个线程取出内存数据为A,操作完变成B准备写入内存,这期间有第二个线程把它修改成了B,第三个线程又把它修改回了A,这时候我写入时发现还是A,会认为期间没有其他线程操作,这就出现了ABA问题。

怎么解决呢,解决的办法也很简单,就是普遍的加版本号,即每次修改内存的值都加一个版本号,只要我上次拿到的版本号和写入时的版本号不一样就证明被其他线程动过了,这时候是继续写入还是退回就看业务需要了。

<think>嗯,用户想了解AQSCAS的概念以及它们的原理。首先,我需要回忆这两个术语的定义。AQSJava并发库中的一个核心框架,用于构建同步器,比如ReentrantLockSemaphore。CAS则是一种无编程的原子操作,用于实现线程安全。 接下来,我需要结合用户提供的引用内容。引用[1]提到AQS的Condition实现,说明AQS内部使用队列同步机制。引用[2]指出AQS的tryAcquire是空方法,需要子类实现。引用[3]提到从零实现AQS,可能涉及队列管理。引用[4]讨论CAS的缺点,比如ABA问题自旋开销。引用[5]提到偏向轻量级,其中轻量级使用CAS。 用户的问题需要详细解释两者的定义原理。首先,我应该分点讲解,先介绍AQS的结构,如CLH队列、状态变量,以及独占共享模式。然后,说明AQS如何通过模板方法让子类实现特定逻辑,比如tryAcquire。接着,解释CAS的概念,包括比较交换的操作,以及它在Java中的应用,比如AtomicInteger。 需要对比两者的区别,比如AQS是框架而CAS是操作,AQS基于CAS实现。同时,结合引用中的例子,比如Condition的实现基于AQSCAS优化中的应用。还要提到CAS的缺点,如ABA问题,使用AtomicStampedReference解决,以及自旋开销的问题。 可能用户是Java开发者,正在学习并发编程,需要深入理解底层机制。所以,回答要结构清晰,分步骤解释,并引用相关资料支持。同时,生成相关问题帮助用户进一步学习,比如AQS的应用场景或CAS的优化方法。 最后,确保使用正确的中文术语,数学公式用$...$格式,独立公式用$$...$$,并正确引用标记。代码示例可能不太需要,但如果有的话用正确格式。检查LaTeX语法是否正确,比如状态变量的表示是否正确。</think>### AQS(AbstractQueuedSynchronizer)与CAS(Compare-And-Swap)详解 #### **1. AQS的定义与原理** **定义** AQSJava并发库中用于构建同步器的核心框架,基于**CLH队列**(双向链表结构)**状态变量**(volatile int state)实现线程同步。通过模板方法模式,开发者只需重写`tryAcquire`、`tryRelease`等方法即可自定义[^1][^3]。 **核心组件** - **同步队列**:管理等待线程的FIFO队列,节点保存线程引用状态(如等待、取消)。 - **状态变量**:`state`字段表示资源状态(如的持有次数),通过CAS操作修改。 - **模式**:支持**独占模式**(如ReentrantLock)**共享模式**(如Semaphore)。 **工作流程** ```plaintext 线程尝试获取资源 → tryAcquire() → 失败则加入队列 → 自旋或阻塞 → 前驱节点释放资源时唤醒 ``` 例如,`ReentrantLock`通过`state=0`表示未定,`state>0`表示定次数[^3]。 --- #### **2. CAS的定义与原理** **定义** CAS是一种**原子操作**,通过硬件指令(如x86的`CMPXCHG`)实现无并发。其操作逻辑为: $$ \text{CAS}(V, E, N) = \begin{cases} \text{更新}V\text{为}N & \text{if } V = E \\ \text{不操作} & \text{otherwise} \end{cases} $$ 其中`V`为内存值,`E`为预期值,`N`为新值[^4][^5]。 **Java中的实现** - `AtomicInteger`、`AtomicReference`等原子类基于CAS实现。 - 示例代码: ```java AtomicInteger atomicInt = new AtomicInteger(0); atomicInt.compareAndSet(0, 1); // 若当前值为0,则更新为1 ``` **优缺点** - **优点**:无、高并发性能。 - **缺点**: 1. **ABA问题**:值从A→B→A,CAS误判未变化(解决方案:版本号`AtomicStampedReference`)。 2. **自旋开销**:高竞争时CPU占用高(优化方法:限制自旋次数或使用分段CAS)[^4]。 --- #### **3. AQSCAS的关系** - **依赖关系**:AQS内部通过CAS操作实现状态变量(如`state`)的原子更新队列节点的插入/删除[^3]。 - **协同应用**:例如,`ReentrantLock`的加流程: 1. 尝试通过CAS修改`state`为1(获取)。 2. 失败则通过AQS将线程加入队列并阻塞。 3. 释放时通过CAS唤醒后续线程。 --- #### **4. 关键区别** | **特性** | **AQS** | **CAS** | |----------------|----------------------------------|--------------------------| | **定位** | 同步框架(/信号量等基础设施) | 原子操作指令 | | **实现复杂度** | 高(需管理队列、状态) | 低(单指令级原子性) | | **应用场景** | 构建高级同步工具 | 实现无数据结构或优化 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值