00:00
好,各位同学,下面我们将对aqs进行源码的深度分析,那么就按照我们从lock方法开始,以re lock的非公平所为例,一步一步,层层递推,步步深入。好,那么同学们,我们这儿呢?如果枯燥的讲源代码,同学们呢,听着呢也比较头疼,我们呢。直接呢?带入一个。银行办理。业务的案例来模拟。我们的。AQS。如何进行?县城的管理和。通知。唤醒机制好,那么现在呢啊,我们就这么干。三个线程。模拟三个。来银行。晚点也就是我们的受理。
01:00
窗口办理。业务的顾客,OK,那么现在呢,很简单了。第一个就是我们的顾客诶。那么他来了以后啊。他是不是要去我们的受理窗口?去办理业务,那么。在这一波的话,那么同学们你懂的是不是A。现产。没问题吧,但是呢,假设呢啊,他办理业务的时间呢,非常长,那比如他办理一堆业务啊。那么这块的话呢,我们那就不是。秒钟,我们就分钟吧,假设它就半个20分钟,那么它首先啊这个A啊,我们来说一下。A、顾客。就是。第一个顾客。此时。
02:00
受理窗口。没有任何人。A,可以直接去办理。OK吧,但是他要办多长时间。是不是半20分钟,那么后面如果来了,后续的线程你清楚的。假设我这个是B线程,那么这个是我们的。第二个顾客。第二个线程没问题吧,那么这个时候你清楚呢。我不管你办什么业务啊,这个B是不是只能在这儿。安安静静的等着。那么。这个时候干嘛?由于受理业务的窗口。只有一个,那么相当于说什么只能一个线程。持有所。此时B只能等待,那么是不是我们所说的进入后客区?
03:02
同学们,这个没问题吧,那么诸如此类,B也就只能在这等着啊,那B完了以后是不是有我们的顾客C呀?那么C也是这么回事儿,他是我们的什么第三个顾客,第三个线程由于也只有一个,此时C也只能等待进入候客区,等待着A办理完成以后,他跟B去抢,能跟上好,那么这个时候的话呢,我们都明白了。A,先占用走起,那么同学们完成了这么一个模块了以后,完成了这点代码以后,我们把。这个业务啊,抽象成一张图。给大家进行详细细致的讲解。三个顾客来银行办理业务,类似三个线程,ABC,一号、二号、三号顾客,我们前面讲过AQS是不是就是一个state加一个队列,这个state前面说过了,是个状态标志位,如果零代表现在没有人抢到这把锁受理窗口。
04:06
没有顾客,绿色就是可以办理,此时是自由状态,那么第一个线程A过来,是不是直接就要进到这个窗口去办理?每个窗口服务一个顾客,相当于是加了一把锁,初始的话没有人,银行刚刚开张,A进来先占先得来到这儿,那么下面这个虚线啊,BC进来了以后,那是不是就得去这个后客区等着。A,办完了以后,这个窗口空出来了,然后咱们再开始啊,好的,那么这个业务我相信呢,很简单,大家呢三言两语说清楚,从代码到这个业务模拟,我们呢一步一步往下走。来。首先,我们先从我们的洛方法开始。按照我们的业务逻辑。A顾客就是第一个,此时受理窗口没有任何人,A直接去办,那么是不是A就进来了,他办的业务时间非常长,干20分钟,后面的B跟C只能等待走起,那么现在我们呢,非公屏锁。
05:09
Lock进来请看,这是C口,这个类调用的是S口的这个lock,那么S是什么?里面的一个内部类,这个类里面又是我们的AQS啊,再看一眼整个AQS啊,我们讲过了,它里面有一个内部的类叫node,封装一个一个的节点,OK,它就是一个媒介载体,那么在AQS这个类里面有一个非常非常重要的变量,表示同步的状态state,就是我们图上的这个信号灯,相当于零,就证明没有人占用这个锁,占用这个窗口可以去办理,OK吧,那别忘了。那么。AQA啊,是队列同步器,那么它有头指针和尾指针,昨天我们也说过了,头尾前后四个指针,好的。那么现在回到这儿了,以后我们呢,洛克,洛克。
06:03
看到没有,这是什么?C这个类里面的抽象方法,那么点开。由公平和非公平第三步,我们是从来自于lock里面的非公平锁。来,走到这儿,大家请看,开始抢占。第一个顾客是A,请看这有个compare and set state,那么这个state什么意思啊?就是设置AQS类里面的这个同步状态,来标明现在我们的银行业务窗口到底有没有人被占用。第一个顾客我想去办理,我们讲过CS了,我希望这个C的值是零,为什么零是绿色,表示窗口无人办理,我当然希望我去银行办理业务的时候没有人,最好是人越少越好,最好没有人,只有我一个人,我是不是一去就能办啊?那么这个时候请看。我7万值是零。我希望这个窗口没有被占用,我能抢到这把锁,如果是的话,那么我就把它变为一代表A抢占到,那么我们来看看比较。
07:06
并设置这个。是个什么意思啊,底层是不是就是一个unf的比较并交换设置这么一个CS的思想啊,所以我说aqs你对他的学习是不是需要有些前置知识,那么CS啊,早就讲过了,不废话,我们希望这个对象的这个内存偏移量的位置,希望没有人占用是零。如果真实值跟我们希望值是一样的,那太好了,我呢直接占用,把它改为一,所以说跑到这儿了以后执行完这段话,那么同学们。我希望值是零,现在初始值是多少就是零,然后呢,A线程第一个线程进来,把它改成几一,然后请看set exclusive owner thread,这是什么意思啊?调用这么一个方法,这个方法哪来的?请看这个方法来自于这个。AQS的负类这么说能跟上,请大家看啊,AQS,我们原来呢说过一个东西。
08:08
他这是不是有个负类,就是谁拥有现在谁持有这把锁,我一点开就是它,那么刚才我们那儿是不是有个设置。占用这个锁的占用这个窗口的线程,现在这个谁是几是A,那么完整的下来以后,我希望窗口没有人第一个顾客过来,直接把它改成1A线程就占到这个窗口开始办理业务,并且将当前占用线程窗口的这个值二设置成是当前线程,那么反映到这儿就是兄弟们,这个只要将会从初始化的初始状态的绿色变成我们的什么红色。这个值变成了几,变成了一,表示已经有顾客占用了。那么现在。第一个占用这个顾客的线程是谁,就是AA直接进到这个窗口开始办理业务。那么第一个顾客。
09:01
过这一波OK吧,好,那么现在回到我们的业务,A进来打出这句话,他在这办理业务是不是20分钟,那么A就在这窗口,这爽着呢,A就一直在这占着这把锁,占着这个窗口,那么接下来唰唰B跟C是不是也就过来了那么一样,B是不是也要去加这把锁,他也想去窗口去办理,那么这个时候B。过来我们点开它占用,他占用非公屏锁的,那么这个时候B也希望窗口没人,然后呢,设置成B自己来占用这个窗口,但是现在事与愿违。我期望值是零。这个值现在是多少?一为什么?A线程是不是已经在这占用着了,所以说没办法。B走不进这个if,它只能走这个acquire,它就是第二个线程,那么请看值都是设为几一代表有一个人占用了这个窗口,因为我们也说过嘛,一个窗口只能是服务一个顾客。
10:07
枷锁只能是一个人。那么用acquire方法。A现在是占着这个呢啊,B没有走if b走的是acquire,那么抢占,那这个时候请看这个里面是不是有三个方法,第一个。第二个。第三个,所以说这个就是我们的AQS的底层源码分析的核心重点,那么也对得上我们的这个脑图,就是这几个方法,我们挨个挨个的敲,那么现在我们呢,B线程就到达了这一步,好,我们小步小步的走,怕同学们学习起来比较困难,我们到这儿完成了第一个方法look,那么得到的第一个结论就是第一个线程A占用,那么。直接续到了这个受力窗口,A已经占了,现在B出来了,B走不了上面这个衣服,只能走L的第二个线程,BC后续就来站这儿,抢不到以后他们就要进AQS队列同步器里面去排队。好,这就是我们的第一步分析,洛克这个方法开始加锁。
我来说两句