并发-AQS原理讲解

125 阅读4分钟

AQS的全称为(AbstractQueuedSynchronizer)抽象的队列同步器,是一个用来构建锁和同步器的框架,使用AQS能简单且高效地构造出应用广泛的大量的同步器。
AQS核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH(虚拟的双向队列)队列锁实现的,即将暂时获取不到锁的线程加入到队列中。

整体概括

image.png 图片来源于:tech.meituan.com/2019/12/05/…

  • 上图中有颜色的为Method,无颜色的为Attribution。
  • 总的来说,AQS框架共分为五层,自上而下由浅入深,从AQS对外暴露的API到底层基础数据。
  • 当有自定义同步器接入时,只需重写第一层所需要的部分方法即可,不需要关注底层具体的实现流程。当自定义同步器进行加锁或者解锁操作时,先经过第一层的API进入AQS内部方法,然后经过第二层进行锁的获取,接着对于获取锁失败的流程,进入第三层和第四层的等待队列处理,而这些处理方式均依赖于第五层的基础数据提供层。

CHL队列

介绍

Craig、Landin and Hagersten队列,是单向链表,AQS中的队列是CLH变体的虚拟双向队列(FIFO),AQS是通过将每条请求共享资源的线程封装成一个节点来实现锁的分配。

image.png AQS使用一个Volatile的int类型的成员变量来表示同步状态,通过内置的FIFO队列来完成资源获取的排队工作,通过CAS完成对State值的修改。

NODE

Node为变体CLH队列中的节点

image.png

线程两种模式

模式含义
SHARED表示线程以共享的模式等待锁
EXCLUSIVE表示线程正在以独占的方式等待锁
image.png

image.png

waitStatus含义

枚举含义
0当一个Node被初始化的时候的默认值
CANCELLED为1,表示线程获取锁的请求已经取消了
CONDITION为-2,表示节点在等待队列中,节点线程等待唤醒
PROPAGATE为-3,当前线程处在SHARED情况下,该字段才会使用
SIGNAL为-1,表示线程已经准备好了,就等资源释放了

同步状态state

private volatile int state;
方法名描述
protected final int getState()获取State的值
protected final void setState(int newState)设置State的值
protected final boolean compareAndSetState(int expect, int update)使用CAS方式更新State

ConditionObject

AQS中的ConditionObject是一个条件队列,用于实现线程之间的等待和唤醒。
它是通过维护一个等待队列来实现的,每个ConditionObject对象维护了一个等待队列,当一个线程调用await方法时,会将该线程加入等待队列中,并阻塞该线程。当另一个线程调用signal或signalAll方法时,会从等待队列中选择一个或多个线程,将其从等待队列中移除,并唤醒这些线程,使其重新竞争获取同步状态。

整体概况

image.png

条件队列

image.png

可重写方法

主要是AQS概览里面的第一层

image.png

JDK中实现AQS简介

同步工具与AQS关联详细介绍
AQS原理讲解AQS原理介绍并发-AQS原理讲解
ReentrantLock使用AQS保存锁重复持有的次数。当一个线程获取锁时,ReentrantLock记录当前获得锁的线程标识,用于检测是否重复获取,以及错误线程试图解锁操作时异常情况的处理。AQS之Reentrantlonk源码解读
Semaphore使用AQS同步状态来保存信号量的当前计数。tryRelease会增加计数,acquireShared会减少计数。Semaphore 源码分析以及AQS共享加解锁
CountDownLatch在多线程并发执行任务时,有时需要让某些线程等待某些条件达成后再开始执行,这时就可以使用CountDownLatch来实现CountDownLatch 源码分析
ThreadPoolExecutor创建线程池中的工作线程worker继承AQS,实现独占资源参考 并发-AQS之ThreadPoolExecutor源码解读(一)
CyclicBarrier多个线程等待彼此达到一个共同的屏障点,然后同时继续执行。并发-AQS之CyclicBarrier源码解读
ReentrantReadWriteLock可重入读写锁,它允许多个线程同时读取一个共享资源,但只允许一个线程写入该共享资源。参考 并发-AQS之ReentrantReadWriteLock源码解读(一)

自定义同步工具

待定

学习参考
1.juejin.cn/post/684490…
2.tech.meituan.com/2019/12/05/…