AQS简介
AQS的全称是AbstractQueuedSynchronizer,在java的并发编程中是非常重要的一个抽象类,它定义了一套多线程资源共享的同步器框架,许多同步类都是以AQS作为底层框架,在此之上拓展对应功能的,如Semaphore、ReentrantLock。
AQS定义了子类继承他后需要解决的大量的细节问题,如获取同步状态、FIFO同步队列等,同时他也已经做好了一些细节工作,减少了实现的工作时间。
编辑
1、Lock:锁接口
2、ReentrantLock:独享、互斥、可重入、公平、非公平、自旋锁实现类
3、Sync:AQS同步器实现类
4、AbstractQueuedSynchronizer:AQS同步器抽象类
5、FairSync:公平锁实现类
6、NofairSync:非公平锁实现类
AQS组成
编辑
AQS由两大部分构成,标识符、FIFO队列。
标识符(state)
- 锁标识符,也叫同步器状态符,在AQS类源码中可以看到是一个int类型的成员变量,标识锁当前状态,ReentrantLock用其标识锁是否被占用、Semaphore用其标识剩余令牌数。
- state配合CAS使用,并由volatile修饰,保证操作原子性。
FIFO队列
- 实质上是一个双向链表,节点Node类是AQS类中的类部类。
- AQS中记录了队列的头部及尾部。
- FIFO队列的作用是当锁被上锁后,新的请求线程请求到锁后加入到FIFO队列中进行等待并尝试获取锁对象。要注意的是前面的逻辑是AQS的实现类的大致逻辑,AQS只是提供了一个模板。根据实现方式不同,可以实现不同类型不同功能的锁。如公平锁、非公平锁,又或者独占锁、共享锁。
AQS获取及释放的标准形式
如前面所说的,AQS只是定义了一个标准化模板,具体实现类由子类实现,其大致实现逻辑如下面文本代码。
//获取
boolean acquire(){
while(当前状态不允许获取操作){
if(需要阻塞获取请求){
如果当前线程不在队列中,则将其插入队列
阻塞当前线程
}else{
返回失败
}
可能更新同步器的状态
如果线程位于队列中,则将其移除队列
返回成功
}
}
//释放
void release(){
更新同步器的状态
if(新的状态允许某个被阻塞的线程获取成功){
解除队列中一个或多个线程的阻塞状态
}
}
结语
本文只简单的记录了一下我自己对AQS底层源码的一些体会。基于AQS的实现类有很多,将起另外篇幅具体描述几个常见实现类的具体实现源码。