00:00
各位同学大家好,接下来我们进入最后一个方法,Acquire q的这个方法的讲解,那么好梳理我们的源码流程。来吧。这个这个这个三大分支一尝试抢占,抢得到锁直接使用,抢不到艾德维塔进入到等待队列里面,然后enq入队,完了以后挨个进去,那么进去了以后他们是如何唤醒通知排队并稳定的在队列里面呢?那么接下来我们就来看看我们最后一个分支第三个调用acquire q的好,下面老规矩,先圆满后理论。来吧。根据我们前面所写所讲,那么acquire。搁到这儿来了,就是这一段,那么下面呢,他传两个参数进来,那么来啊,同学们请看一眼,那么相相当于说现在啊,我们。顺着按照我们的顺序过来,先是B后是C,对吧?那么下面比如说现在传的这个方法,艾维塔就是我们的B,根据我们的入队的规则,艾德塔给你排进去了,那么下面呢,我们传的就是B,好,这个node就是b int,那么这个参数,那么也就是我们刚才所说的传过来的这个是一对吧,我们都想。
01:20
零是空弦,一是占用,改我们的这个值,好的这个是B,那么下面呢,过来请看。这个是这个是finally,那么fail。是错。TRY是我们的正常执行finally,如果这个if failed是true的话,那么做我们的一个什么取消,那么他的意思就是说,呃,正常情况下我们该怎么用,怎么用异常情况,那么什么概念,比如说啊,就像我们银行办理业务。假设后面还有BCDEF好多个人等着,等着C节点说我不想等了,这块时间太长,我改天来办,他是不是可以出队,哎,那么所以说我们后续也会和大家讲一下这个取消这种情况,那么目前我们回过神,先把正常流程走通再说异常情况好了,我们过来这这个file指出就是一个变量interrupt,那么也有可能哈,比方说现在这个突然银行断电了,我们要中断我们的业务,那么默认不中断,相当于说这些异常情况我们都先不考虑来吧,走正常情况。
02:25
Interrupt呢,也是for啊,那么这你去看又是个。类似于自旋一样的一个大循环,对吧,走吧,那么第一个节点是BB,完了以后是C,所以说现在请看B节点的。Pretty,那么这个时候大家请看pretty是什么意思啊,前置节点的意思就是获得我当前节点的这个前置节点,好,那么同学们请看现在是no是BB的前置节点,就是这个P10B的前置节点,是不是我们的头节点,也就是我们这的这个虚拟节点占位节点,OK,好,那么现在要求这个虚拟节点就是头节点to还是force to,为什么头节点刚好指着它B节点的?
03:10
前一个节点,那么就是这个虚拟节点,虚拟节点目前就是pad头节点,回答正确,OK,那么如果这个是to,那么接下来干什么呢?请看A。又是try a块什么意思啊,这个TRY块我们是不是前面讲过,意思就是说。进去入队的这个B也不老实啊,虎视眈眈的看着这个窗口,只要有空闲,那么他干嘛马上想第一时间去争夺资源,也是try acquire再尝试啊,再强抢,OK,那么这个try acquire前面我们也已经给大家介绍过,对吧,就是它,那么acquire现在又回到这个方法,意思就是说我排着队的时候,我要盯着那个窗口,资源只要一释放,我马上再抢抢好,那么现在。搁到这儿,那么按照我们的业法,我们都清楚,我们现在这个B没办法,那么现在呢,这个B又过来执行一下,这个方法非公平所得TRY快啊,按照我们的业务所讲解,这个A是不是要办很长很长时间,相当于说这个串再强抢也是失败,它返回了false,好,那么如果他这。
04:16
返回了first,我们呢,就好办了,这个是错,这个是first进不进来,不进来这一段,所以说继续往下走,这有个should park after failed acquire,那么来。进入到这个方法,那么这个方法呢,既是一个状态的改变,也是一个判断的返回,因为人家返回的布尔值啊,那么这个P什么概念,就是头节点,哦,抱歉,就是前B节点的前置节点,目前就是我们的头节点虚拟节点,而这个节点就是我们的B,好吧,进来我们搁到这儿前置的这个,那也就是现在当前我们的虚拟节点,那么现在前置节点的位置。WS等于多少?我们大家都晓得,这个时候默认值这个int类型,前面我们是不是说过wait什么型,Int型的,怎么着当前节点在队列中的状态,零是当一个node被初始化的时候的什么默认值啊,我们都晓得,根据前面我们一步步的讲解和推演,这个6NODE6出来的100%这个值是多少,是零好了。
05:18
那么现在相当于说这个西格是几?是负一,那么现在这个值是零,零等于负一吗?当然不等于了,不进了LC负现在是多少?零,零大于零吗?当然不OK了,也不进来,所以说if l以后只剩它,请看compare and set,注意它的意思就是把前置节点,也就是我们现在的这个头节点。WS啊,就是wait塔,这个值改成no,西格改成什么负一,OK,然后返回false,明白,所以说在这儿,那么抱歉,我这个值就已经变成了负一,Sign格al由默认的零变为了负一,OK好了,那么这儿返回什么负好了,那返回false以后来相当于这个if是false,那么就不往前走了,那么跳出来来,这又是一个循环,再回来一次啊,那么这个no就是我们的B节点,B节点的前一个节点就是这个PP是谁?就是我们的虚拟的这个占位节点,它是头节点吗?是的,然后呢,再尝试抢抢,那么根据我们的业务,这个A要占用很长时间,抢夺失败,这是force这段补进来,结果又进来到这,那么这个P就是我们的现在的虚拟节点。
06:35
这个no就是我们的节点B进来。那么好,那么现在我们P达就是前面这个节点的韦塔菲塔,是不是等于西格塔?当然是了,根据上一步是不是已经是等于负一西格塔,那么大家请看,你记不住的话,停留在这儿看一眼S格al就是负一,OK,那么所以说这个时候注意返回了什么,第二次进来人家返回了是to了,好的,那么有处了以后来,相当于说这个就是处,并且的关系继续往前搞,请看park and check interrupt,那么。
07:08
点进来,这个时候我们的B我们过来这儿,大家请看lock support.park明白为什么之前我们要讲lock support了吧,如果没有前面的基本功,你是根本不可能读得懂AQS的,所以说现在来问你谈谈你对AQS的理解,有没有读过AQS的源码,有些人的硬去背,厉害的面试官直接问你,那你跟我说一下,他怎么稳稳当当的入队的,怎么停在这儿的底层,靠的是洛克support.park那么这个park我们都清楚是不是卡在这儿,所以说this。谁就是我们的B,那么搁到这儿了以后,我们就会得到我们的结论,这个时候这个B就在这儿转着圈进来了,OK,好,那么所以说,那么在这儿为了后续好给大家讲解。那么允许我呢,先抓张图啊,那么相当于说在这一块的以后,那么同学们,那么搁到这儿,我们呢,可以看到。
08:02
搁到这儿了,以后那么来这些啊,其他不相关的戳你的眼睛的,我先把它删除好注意这儿。有一个park and check interrupt OK,好。点进来,我们跟刚才所讲lock park,说明我们这个this,就是当前B就停在这了,好,那么再给它。画个图。那么。两个图干脆合二为一。方便大家理解意思就是说。这个park and interrupup就是这个方法,那这个方法啊,请看又是我们的一个look support park OK,那么说明什么?说明我们在这,我们第一个线程就是我们的这个B。明白,就在这儿转着呢,OK,洛克斯波的part,我们相当于说是不是就稳稳当当的规规矩矩的就停留在这个队列里面了,OK,所以说到这儿,这个B它才稳稳当当的停留在这,并且在这儿support.park断着呢,OK,等着后面的唤醒通知机制好,那么。
09:16
完成了我们的B,那么接下来再来,别忘了我们还有C呢,对吧,那么得到这,那么同学们,我们直接。过来。C呢,和刚才的这个B也一样的流程,那么刚才艾德维塔是B就进去了,整套流程完成,那么B完了以后是CC呢,也要重复前面的流程,那么过来acquire q的,那么现在这个node就不是B了,这个node就是我们的什么C。好了,Fair to interrupt,这个放下不表,后面聊,那么暂时默认过来,C进来以后也是一个循环,OK,那么现在。
10:00
C节点的前置节点是这个P,这个P是had吗?Force,当然不是啊,因为C节点现在的前置节点是我们的节点B,所以呢,这个动作根本就不用再往前拱了,直接就是false进来,然后C节点过来这儿。同样的调用这个方法,那么前置节点这个P现在就是B,这个节点就是COK过来,那么现在P就是BB节点的维塔塔是几?那么大家请看B节点的当前节点状态是几?是不是就是零啊?那么也就是WS就是零,零等于负一吗?不等于不进,零大于零吗?不等于不进。所以L同样设置compare and s塔就把前置节点的WS设置为什么sal,大家有没有发现都是后面这个。把前面这个给他设置了,所以说到这儿C又会把B的signal。又会,那这个C又会把我前面的这个B的wait塔这个状态由默认的零改为什么S格负一,OK,然后返回负四好了,那么所以说隔到这儿。
11:12
C如果进来以后也把它改成了负一好了,那么返回false走走走,那么搁到这儿了以后,由于这儿呢,返回一个false,也就不再继续往前走啊,是个大循环对吧?那么来了搁到这,这是节点CC的前一个节点是BB,等于头吗?当然不等于了,现在头节点是这个虚拟节点,当然不是B,所以说在这儿就是false,根本也不会往前拱,If不进来,那么然后还是跑到这个方法里面,大家请看这个就是前置节点C的前置节点就是B。这个node就是C好了,那么下面搁到这儿,B节点的维塔塔现在WS等于多少等于负一,那么来请看。负一等不等于负一。
12:01
当然等于了,所以这返回什么错,OK好了,那么所以说在这一块就返回,并且的关系继续往前搞,那么这个时候就是park and check interrupt过来,那么搁到这look support.this是几是C,所以说搁到这儿了以后,我们才明白,现在C也就乖乖的干嘛,和这个B一样,也就在这断着了。OK,在这什么停滞着?那么等待着后面的出对入队和通知唤醒,那么所以说同学们,我们到这儿我们可以会发现都是什么后面的节点会把前面的这个wait改为负一,听到那么来搁到这,我们可以看看何为负一,S表示线程已经什么准备好了,就等待着资源示范,那么按照先入先出的规则,那么是不是一些负一的先出去。对吧?好,那么队列就是这样好了,那么搁到这儿了以后那同学们三个方法完成,那么彻底给大家讲清楚了,他们是如何尝试抢占,抢占不到入队,然后再在队列里面坐稳了,就有这么三步好了,那么下面小复习一下,看看前面的流程,那么acquire q的,那么尝试继续什么抢占。
13:17
在队列里面站稳了。那么走起。主要就这个方法,那么就是看前置节点对吧,那么注意park,那check interrupt这个没结束呢,啊各位亲,在这B跟C,由于这个lock support.park那么自然而然是不是应该有方法叫安帕把B跟C给唤醒,然后我们再去干活了,所以说在这儿兄弟们我们没完了,我们在这停滞着呢,挂起了,你可把它理解为OK,好了,那么来喽,这些介绍完了以后呢,走。假如再抢抢失败,就会进入这个东东,什么叫再抢抢失败,就是这个方法,Try acquire,听懂了吧?好,那么下面呢,我们这三个方法呢,也介绍过,Should park after acquire,就是是否应该park,如果说是。
14:03
抢占失败对吧,然后呢,帕克挂起了,来检查一下是正常的挂起还是说有中断,那么来在这个方法,那么就先是这个,然后这个说穿了,这一圈流程过来,就按照我们的C,那么来完成了lock support的这个park,至于说其他的111,我们现在呢,暂时还用不到,后面我们再讲,尤其是这个大于零的时候,好,那么接下来呢,过来看它,看看它,是的park after field acquire,那么说到这儿,那么同学们。前置节点和我们的当前节点,那么获得前驱节点的状态,比如说我们都清楚第一次是B,好吧,这个节点是B,然后这个P是我们的哨兵节点,那么哨兵节点WS它的状态如果是sign及等待被占用的资源释放,直接返回处,否则的话,由于第一次进来我们默认是零嘛,是吧,所以说都不走这儿,我们会走到这儿。相当于说我们呢,将这个前置节点的wait塔这个状态由默认的零换成负一,前面讲过它是干什么呢?将当前节点的前期节点设置为sign状态,用于后续的唤醒操作,因为马上我们就要讲如何出队了,我这些状态是有关系的,所以说都要混个眼熟程序第一次直线到这返回是false,还记得吧,我们说过直线到这儿第一次是false,第二次完了以后把它改为signal了才会返回错,还会进行外层的第二次循环,最终那么从第七行返回,那么就是在这儿return true返回,有印象吧,这个呢,我们刚才都说过了,所以说呢,如果前区节点的为塔是西格记,这个方法呢,就会返回错,OK,我们两次啊。
15:45
那么返回处理后,程序会继续向下执行park check interr的方法,用一项当前线程挂起,那么相当于说B跟C到这一步了才是稳稳的入对了,就在这好好的等着了,OK,好,那么接下来呢,这个叫park check interrupt,我们刚才也说过了,这个park,那就是当前线程挂起,程序不会继续向下执行,那么。
16:06
后面什么时候被唤醒呢?那么就是三种情况,那么当然啊,我们这儿呢,就不再说这个不合逻辑的或者是中断的那些情况,没那么复杂,那么自然而然,是不是等着所释放以后就要唤醒队列里面排队的BCDFG这些排队的安帕以后你们再去抢资源,好,那么各位同学,这个就是我们的三个方法,从尝试强所到入队,到最后入队坐稳了,那么现在排好队,那么是不是要等着我们的接下来的下半场A总有一段时间把锁按洛克释放了吧,释放了以后这个状态。终于从红色的一变成了绿色的零,空闲了么?排队的这些是不是挨个挨个出队去抢资源了?好,那么同学们入队就给大家呢介绍到这儿。
我来说两句