AQS全面解析

一、前置知识

二、是什么

2.1 字面意思

抽象的队列同步器

通常地,AbstractQueuedSynchronizer简称为AQS

2.2 技术翻译

是用来构建锁或者其它同步器组件的重量级基础框架及整个JUC体系的基石,通过内置的FIFO队列来完成资源获取线程的排队工作,并通过一个int类变量表示持有锁的状态。

三、AQS为什么是JUC内容中最重要的基石

3.1 和AQS有关的

3.1.1 ReentrantLock

3.1.2 CountDownLatch

3.1.3 ReentrantReadWriteLock

3.1.4 Semaphore

3.2 进一步理解锁和同步器的关系

3.2.1 锁

锁,面向锁的使用者,定义了程序员和锁交互的使用层API,隐藏了实现细节,你调用即可。

3.2.2 同步器

同步器,面向锁的实现者,比如Java并发大神Douglee,提出统一规范并简化了锁的实现,屏蔽了同步状态管理、阻塞线程排队和通知、唤醒机制等。

四、能干嘛

4.1 加锁会导致阻塞

有阻塞就需要排队,实现排队必然需要有某种形式的队列来进行管理。

4.2 解释说明

抢到资源的线程直接使用办理业务,抢占不到资源的线程的必然涉及一种排队等候机制,抢占资源失败的线程继续去等待(类似办理窗口都满了,暂时没有受理窗口的顾客只能去候客区排队等候),仍然保留获取锁的可能且获取锁流程仍在继续(候客区的顾客也在等着叫号,轮到了再去受理窗口办理业务)。

既然说到了排队等候机制,那么就一定 会有某种队列形成,这样的队列是什么数据结构呢?

如果共享资源被占用,就需要一定的阻 塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列的变体实现的,将暂时获取不到锁的线程加入到队列中,这个队列就是AQS的抽象表现。它将请求共享资源的线程封装成队列的结点(Node) ,通过CAS、自旋以及LockSuport.park()的方式,维护state变量的状态,使并发达到同步的效果。

五、AQS初步

5.1 AQS初识

5.1.1 官网解释

有阻塞就需要排队,实现排队必然需要队列

AQS使用一个volatile的int类型的成员变量来表示同步状态,通过内置的FIFO队列来完成资源获取的排队工作,将每条要去抢占资源的线程封装成一个Node节点来实现锁的分配,通过CAS完成对State值的修改

5.2 AQS内部体系架构

5.2.1 AQS自身

1.AQS的int变量

AQS的同步状态State成员变量

类似于银行办理业务的受理窗口状态

零就是没人,自由状态可以办理

大于等于1,有人占用窗口,等着去

2.AQS的CLH队列

CLH队列(三个大牛的名字组成),为一个双向队列

类似银行候客区的等待顾客

3.小总结

有阻塞就需要排队,实现排队必须需要队列

state变量+CLH双端Node队列

5.2.2 内部类Node(Node类在AQS内部)

1.Node的int变量

Node的等待状态waitState成员变量

等候区其它顾客(其它线程)的等待状态

队列中每个排队的个体就是一个Node

2.Node类讲解

内部结构

属性说明

5.3 AQS同步队列的基本结构

AQS底层是怎么排队的?

是用LockSupport.park来进行排队的

六、从我们的ReentrantLock开始解读AQS

6.1 ReentrantLock原理

Lock接口的实现类,基本都是通过【聚合】了一个【队列同步器】的子类完成线程访问控制的。

6.2 从最简单的lock方法开始看看公平和非公平

6.3 ReentrantLock代码分析

6.3.1 lock()

非公平锁走起,方法lock()

对于上述过程,A顾客进来,窗口没有人,也就是State状态初始时为0。然后,A成功进入窗口办理业务,将状态State设置为1,此时银行受理业务窗口,即Thread=ThreadA。

6.3.2 acquire()

6.3.3 tryAcquire(arg)

6.3.4 addWaiter(Node.Exclusive)

总结:双向链表中,第一个节点为虚节点(也叫哨兵节点),其实并不存储任何信息,只是占位。真正的第一个有数据的节点,是从第二个节点开始的

6.3.5 C线程进入情况

6.3.6 acquireQueued

shouldParkAfterFailedAcquire

如果前驱节点的waitStatus是signal状态-1,即shouldParkAfterFailedAcquire方法会返回true,程序会继续向下执行parkAndCheckInterrupt方法,用于将当前线程挂起。

parkAndCheckInterrupt

此时,B,C都在阻塞等待着

6.3.7 unlock方法

A线程在窗口办理的差不多了,此时该调用unlock方法了

此时再回到原来,B还在阻塞等待

非公平锁是来了先抢一次,抢不到进入队列等待。

视频教程processOn流程图

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值