当前位置:网站首页>【无标题】
【无标题】
2022-07-01 08:15:00 【今天学不学?】
AQS
AQS在java并发中的地位,相当于JVM在java中的地位,他就是抽象阻塞队列同步器,是实现同步器和锁的基石,就是base父类
抽象类:相当于base父类,可以是很多类的模板框架,组件,在抽象类的子类有很多情况
队列:用于锁的争抢,没抢到资源的到阻塞队列排队
概述:用于实现锁和其他同步器组件的公共基础部分的抽象实现,是重量级的基础框架以及JUC体系的基石,就是一个抽象FIFO队列来完成资源获取线程的阻塞队列和一个int变量的状态来表示当前资源是否被占用
Java中的大部分同步类(Lock、Semaphore、ReentrantLock等)都是基于AbstractQueuedSynchronizer(简称为AQS)实现的。AQS是一种提供了原子式管理同步状态、阻塞和唤醒线程功能以及队列模型的简单框架。
在AQS中的锁类型有两种:分别是**「Exclusive(独占锁)**「和」**Share(共享锁)」**。
「独占锁」就是「每次都只有一个线程运行」,例如ReentrantLock。
「共享锁」就是「同时可以多个线程运行」,如Semaphore、CountDownLatch、ReentrantReadWriteLock。名称为AbstractQueueSynchronized,是阻塞式锁和相关的同步器工具的框架
概括:整体上就是一个抽象的FIFO队列来完成资源获取线程的排队任务,并通过一个int类变量表示持有锁的状态

AQS框架
AQS框架图

AQS内部体系框架

数据结构
AQS最基本的数据结构为Node节点

属性解释:
waitStatus:在队列中节点的状态
thread:当前节点的线程
prev:前驱节点
predecessor:返回前驱节点,没有的话抛出npe
nextWaiter:指向下一个处于CONDITION节点
next:后继指针
waitStatus属性值种类:
| 枚举 | 含义 |
|---|---|
| 0 | 当一个Node被初始化的时候的默认值 |
| CANCELLED | 为1,表示线程获取锁的请求已经取消了 |
| CONDITION | 为-2,表示节点在等待队列中,节点线程等待唤醒 |
| PROPAGATE | 为-3,当前线程处在SHARED情况下,该字段才会使用 |
| SIGNAL | 为-1,表示线程已经准备好了,就等资源释放了 |
源码分析
从ReentrantLock中的非公平锁来进行源码分析
从lock方法进行入手
ReentrantLock实现了Lock接口,里面包含了一个sync同步器,该同步器继承了AQS类,底层lock调用了sync同步器的lock锁
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
lock.lock();
try{
//同步代码块{}
}finally {
lock.unlock();
}
}
2.sync同步器的lock方法
- 首先CAS进行判断,能否当前线程先抢到锁,如果成功,该线程直接获取资源,否则进行acquire方法尝试获取资源
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
3.acquire方法
该方法主要有三大体系
- tryAcquire:尝试获取锁,如果再次没有获取到锁,返回false,进行addWaite(Node.EXCLUSIVE)r方法的执行
- addWaiter(Node.EXCLUSIVE):如果没有获取成功,将线程加入到队列中
- 最后调用acquireQueued()方法:通过 “死循环”的方式获取同步状态
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
加入队列的时机
当执行acquire(1)时,会通过tryAcquire获取锁,在这种情况下,如果获取锁失败,就会调用addWaiter加入到等待队列中去
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();//先获取资源的状态
if (c == 0) {
//如果为0,表示该资源没有被占用,可以进行获取
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);//获取资源,返回true
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
//如果获取的资源线程为当前资源线程,返回true
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
如何加入队列
获取锁失败后,执行addwaiter加入等待队列
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);//新建一个node节点
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;//取出当前尾结点
if (pred != null) {
//如果尾节点不为空 说明队列已存在阻塞线程
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);//如果尾节点为空,表示阻塞队列中还没node节点,进行入队操作
return node;
}
入队操作
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) {
//进行队列的初始化
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZUKGENuu-1656424435234)(C:\Users\小刘同学\Desktop\入队操作.png)]
等待队列中线程出队时机
前驱是头结点,就获取到了同步状态。
head节点表示获取锁成功的节点,当头结点在释放同步状态时,会唤醒后继节点,如果后继节点获得锁成功,会把自己设置为头结点,节点的变化过程如下
这个过程也是涉及到两个变化
- 修改head节点指向下一个获得锁的节点
- 新的获得锁的节点,将prev的指针指向null
这里有一个小的变化,就是设置head节点不需要用CAS,原因是设置head节点是由获得锁的线程来完成的,而同步锁只能由一个线程获得,所以不需要CAS保证,只需要把head节点设置为原首节点的后继节点,并且断开原head节点的next引用即可

边栏推荐
- [question brushing] character statistics [0]
- shardingSphere
- 【js逆向】md5加密参数破解
- Internet of things technology is widely used to promote intelligent water automation management
- [untitled]
- Leetcode t29: divide two numbers
- MATLAB小技巧(23)矩阵分析--模拟退火
- Provincial election + noi Part VI skills and ideas
- How to recruit Taobao anchor suitable for your own store
- Anddroid text to speech TTS implementation
猜你喜欢

Adding color blocks to Seaborn clustermap matrix

Koltin35, headline Android interview algorithm

Learn reptiles for a month and earn 6000 a month? Tell you the truth about the reptile, netizen: I wish I had known it earlier

Intelligent water supply system solution

Hijacking a user's browser with beef

【入门】输入n个整数,输出其中最小的k个

shardingSphere

【入门】取近似值

Internet of things technology is widely used to promote intelligent water automation management

Intelligent constant pressure irrigation system
随机推荐
Precautions and skills in using regular expressions in golang
Codeworks round 803 (Div. 2) VP supplement
Intelligent water and fertilizer integrated control system
Leetcode t31: next spread
Tita OKR: a dashboard to master the big picture
[getting started] extract non repeating integers
uni 热更新
Yolov5 advanced 7 target tracking latest environment setup
XX攻击——反射型 XSS 攻击劫持用户浏览器
如何招到适合自己店铺的淘宝主播
[untitled]
[redis] it takes you through redis installation and connection at one go
[untitled]
shardingSphere
empirical study and case study
01 numpy introduction
Provincial election + noi Part III tree problems
[untitled]
On several key issues of digital transformation
Anddroid text to speech TTS implementation