00:00
通过乳化脚本,我们已经可以保证判断和删除之间的原子形了,并且呢,可以防止误删。那我们接下来呢,还有一个比较重要的问题要去解决一下啊,当然了,不是自动续期啊,在讲自动续期之前,我们还有另外一个比较严重性的问题,就是搜索问题,那么还有一个思索问题啊。那么这个四个问题呢啊,就是我们的不可重入也可能会导致失算啊。不可重入可能会导致思索。那么可同入索呢,我们可以呢,再简单的解释一下,那么比如说呢,我有一个A方法,那么A方法里面呢,我可能会通过什么塞,什么是lock。好,来句或解锁。那最后呢,来一个NX或取道索啊。那么然后呢,我开始去执行业务操作啊,执行这个业务操作,那在执行业务操作的时候,我可能会调用一个B方法,那么最后呢,我来去啊释放锁哈,在执行完所有的业务操作之后呢,来去释放锁,然后是通过撸R脚本,最终呢,肯定是通过DL指令来去释放锁的。
01:10
啊,第一要指定释放锁,把那个锁呢给它释放掉。那么这个B方法,那B方法呢,它这里呢,比如说有一个B方法,那么这个方法呢,它可能也需要通过那么set lock来以保证现场安全来去获取锁。然后最后呢,来一个N一个四这样子。然后再执行业务操作,那最后呢,来去,那么释放锁,释放我们的lock锁好,那么现在我们来分析一下啊,可能会存在什么样的问题。那么一个请求过来了,首先会到达我的A方法。那么执行A方法,让他获取这个lock锁,那于是我的release服务里面,那么这个lock锁呢,就会被被占用了。啊,被占用了。那被占用过之后呢,来看他开始进入我们的业务方法,比如说这里呢,已经获取所成功了啊,来执行我们A的业务方法。
02:05
那么执行到B方法这个位置的时候,然后呢,进入我们的B方法啊,那在B方法里面,它首先也要去获取一个lock锁,那这个lock锁。那跟A呢,是同一个拉锁,名字都一样。那会怎么样呢?哎,他会在这里一直尝试来去获取我们的拉索。那会怎么样呢?一直获取不到。因为这个锁呢,被A给占用着。那么A呢,只要不去释放这个锁,那么我的B呢,是会一直在这里进行重试,一直在这里进行重试然的或解锁。那么知道获取到所为罪啊?回到手为止,那能重试成功吗?成功不了,因为这个锁呢,一直被A给占用着。那么A呢,要释放所得,要等呢,等B方法执行完了,执行完了,B方法执行完了,A方法才能执行完,那进而呢,才能去释放这个锁。
03:01
而B方法要执行完,他首先得要获取这个锁。来获取到锁之后呢,哎,他最后释放的锁才能执行完哈。哎,那A方法呢,要等B方法执行完。那B方法呢,要等A方法呢,执行完了,释放锁他才开,才能开始执行。那就构成了一个啊死的死的依赖关系了。那么A要等B,那么先执行完,他才能去释放所。那B的话呢,要等A执行完了,那么释放锁了,那B才能去执行。那于是呢,就会产生我们的思索问题啊。啊,那么如果我的锁是可重入的,那就可以避免这种情况啊。好,那么咱之前呢,其实接触过这个可重入锁,比如说呢,我们那个re lock,你从字面意思就可以理解出来,它是个什么锁呢?是一个可重入锁啊reinent lock就是可重入锁。
04:02
那么软硬程lock它怎么实现可投入的呢?好,我们可以看看lo底层原理是什么样子的啊,那然后呢,后续我们来模拟lo的底层原理。我们也去写一个。可重入错。接下来呢,我们就保证我们的锁呢,它的可重入性啊,可重入性。好,那么所以呢,咱第六个特征,或者说第五个特征,咱可以保证可重入可重入性。然后第六个特征呢,我们再去做这个自动续期,因为咱的可程度性呢,要比自动续期呢,更加迫切一点。啊,那么可重入性怎么保证呢?我们可以去参照称lock源码啊,我们来去分析一下。好,那我们来找到的那个人称lock,咱该就第一个版本的那个方法里面在使用这个可同入。那么可重锁怎么加锁的,又怎么解锁的?好,我们先去看一下人称lock的各档法啊,它的各档法呢,可以是无参的,也可以是有参数的啊。
05:10
你这个午餐的构造法里面会给我们这个think属性,给它有一个think属性。然后呢,创建一个非公平的同步器。你也可以是有参数的,如果有参数的情况下,你这个参数是布尔类型的啊,这是一个三元表达式,如果这个分非尔为处,它会创建一个公平的同步器。那么如果是为false的情况下,那么它会给这个think赋予一个非公平的同步器。好,那么在这的话呢,为false的情况下啊,它和这个是一样的。哎,咱不写参数就相当于是非公平的,如果写了一个处代表是公平的,如果写一个false也是一个非公平的啊。啊,那么这些都是什么东西呢?来看,不管是fair think还是none fair think,他们呢,都继承自啊,继承自我们的think。
06:03
那么这个think呢,又是什么东西呢?它是一个内部的,抽象的,静态的一个内部类,你看这个think内部类。是图像的啊,因为这个nonfi和这个feel都是think的子类。那么这个think呢?又是谁呢?它又继承自我们的aqs。只要对我们GC那么有所了解的情况下,那么都应该知道这个AQS啊,那么is呢,是咱GC里面所有锁的一个基石。哎,不管是我们这个re lock,还是re read write lock啊,Read right lock,以及呢,什么countdown。看得到两个是。看得到large以及呢,咱们那个simple那么信号量。啊,不管是像我们的那个独占所还是这些共享所哈,那么他们的底层都是AQS。
07:01
那么IQS呢,咱就不做不多介绍了啊,那三个呢,就抽抽象队列同步器,抽象队列同步器它底层呢,有两部分组成,那么一个是呃,T这样的一个玩意儿。它是一个int类型的啊,所以呢,默认值只能是。方是零,然后是VO语义的啊。Volunteer啊,语义的啊,这样的一个set set变量。那么然后呢,还有一个呢,是好呢,是咱们的,呃,Ay队列啊。啊,Fi,然后O队列,什么是fio呢?就是first。First in。用的是first。First and out,就先进先出的队列啊,先进先出队列。那么啊,咱可以呢,基于这个AQS,那么来去实现我们的锁,比如它可以实现在我们这个程lock里面,可以实现我们的公屏锁和这个非公屏锁。
08:02
那么如果我们使用这个AQS来去实现非公心锁,那么它原理是什么样的呢?它工作原理是这样子的啊,比如说呢,首现一个请求,他会干嘛呢?他会先去来一个CS操作。C操作,然后呢把的值呢从零设置为一。看你的原始值是不是零,如果是零就把它设置为一,如果这个CS操作成功了。那么就代表呢,获取锁成功了啊,就强所成功。哎,那么如果这个CS操作失败了,那怎么办呢?他就会跑到后面去排队啊。就排队,那比如说咱们秒杀的情况下。秒杀情况下,哎,那么他已经很多人这里啊,想着去买这个商品了。个人呢,抢到锁了,已经秒杀成功了,那秒杀失败的只能跑到这个后面去排队啊。那么又来了一个请求,我们来一参与秒杀,首先呢,会在会进行CS操作,看有没有人会持有这把锁,看来值是不是等于零。
09:04
如果等于零,说明没有人有锁啊,那于是咱CS呢,就可以操作成功,然后获取这把锁。灰制发酸呢,可以减固存,研发成功。那么如果呢,有人有了这把锁呢?这三值不等于零呢?是不是已经有人有锁了,那么你的CS必然会失败?那么失败的情况下,你又只能跑到后面去排队了啊。这个一般是非公平锁的情况下。我们就很看运气啊,你运气好,你可能一一上来呢就抢到了啊。然后呢,那就可以去减库存了。那么如果你运气不好。那会怎么样?你可能比如你是第二个来的,但第一个呢,已经把这个锁给占用了,那你第二个来的只能干嘛呢?只能在这个队列里面一排队。所以呢,呃,咱如果使用非公明锁啊,看的是运气啊,你可能来的比较晚,但是你一你一上来呢,就抢锁成功了,你来的比较早,来的比较早呢,但你没有抢到,你可能排的比较靠前,排的排的比较靠前也没有用啊,因为别人可能会有不停的有人来插队,不停有人来插队啊,你可能还是买不到。
10:10
他就会这样子。啊,那么公平所怎么回事呢?公平锁呀,是这样的啊,咱不会对set set进行C操作的,先干嘛呢?先去到队列后面的一排队。啊,如果有人排队,那到后面去排队,那如果没人排队的话,这队列为空的情况下,咱才能去对带值来进行CS操作,让他获取锁哈。好,那么在生活中呢,其实咱们也有这种例子,比如说呢,你去买早餐,在这里呢,有一个包子铺啊,非常受欢迎,对不对啊,那每天早上呢,都排满了人啊。PIN。那比如说呢,你一上来英语插,对诶老板买一个啊,来个肉包。然后呢,如果老板给你拿包子了,那你插队成功。哎,这个呢,就含的就是非公命锁哈,就是非公命锁。
11:00
那么如果老板不让你插队,就到后面去排队去。那怎么办呢?那你只能到后面排队了呀。OK,这就非公开的场景了。啊,那么如果是公平所怎么样呢?哎,大家呢,都老老实实去排队啊,然后呢,先来先先排在排在最前面,那后来呢,排到最后面对吧?哎,这就是公平所了啊,没有人插队啊,如果每个人都想来插一次队的话,就是非公平所。OK,那么这是咱们,呃,这个IQS它的一个呃,底层结构啊,啊是有一个T这样的一个东西,但强锁呢,本质是对sta来进行抢啊。啊,进行CS操作来影响的。那如果抢到了,哎,非公线,如果抢到了非公应锁哈,那么就就就成功了。啊,那么如果你没有抢到,那它就会进入咱们这样的一个队列里面去啊,它有一个fio队列这样子。好,那我们呢,不做过多介绍了啊。那我们来看一下咱们这个,呃,非公平锁,咱以非公平锁为例,非公平的可重复锁为例,它是怎么工作的。
12:07
好,咱们打开这个。嗯,打开我们这个service啊,来看这个加是怎么加的啊。来点开这个加锁方法。那么这个加锁方法呢,那它掉了一个think里面的lock方法,哎,咱们的think里面有没有lock方法呢?那think不就这个think对象吗。好,那么这个先看这个同样类里面哈,它有没有lock方法。那我们点开看一下,应该有这个lock方法,但这个lock方法是一个抽象的方法啊。抽象方法,那么它的实线在哪里呢?好,我们现在使用的是非公平锁的实现,那在非公平锁情况情况下,那么它这个lock呢,实现在这个地方呢。你先干嘛?一上来先做一个CS的判断。啊,对的值进零一操作。
13:00
啊,期望值是零,然后目标值呢是一更新为一,如果CS操作成功了。那么最开始设置当前线程,那么是排他拥有者线程。好,那我们可以去看一下这个CS啊。那么CS呢,我们知道它那个全称啊,是compare and and。And sweep啊,And sweep,但是最常见的方法呢,是can and set方法。那。那么这个方法呢,来看一下啊,它就对我们这个set值进行set操作,有一个ona。那么on呀,它呢是JDK给咱留的一个后门哈,我们知道Java呢是面向对象的。面向对象的。啊,那么这个on呢,它提供了一个指针,哎,它可以通过指针的形式来对我们内存里面的变量来直接进行操作,啊,我们的Java呢,是没有指针的啊。但一切都是通过对象来操作的。
14:01
来,那么这个on呢,就提供了一个后门,咱可以通过指针对内存中的变量,那么直接进行操作了啊。啊,它里面呢,给咱提供了大量的这种硬件级别的。硬件级别的啊级别的咱的CS原子性操作啊,原子性操作就它的这个比较并交换。比较交换是原子型的。啊,中间呢,不会被打断。那说这个操作呢,是一个原子性的啊。OK,那么来看一下,那么这个Z4啊是啥呢?指我们当前这个as这个对象啊,This对象吗?然后呢,是state of set。Set是什么东西呢?是偏移量,是色态的属性,在我们这个对象里面的偏移量,那么this呢,是指上的是一个对象地址啊,然后根据个偏移量。那就可以拿到。我们猜测。这个变量在四在当前这个对象里面的这个位置了啊,跟这个位置跟我们对象地置,再给你偏移量,就可以找到T这个属性在我们内在我们内存中的位置了。
15:13
然后呢,再根据期望值。是不是等于我当前这个期望值。让他来去决定要不要更新。好,这个死抬offset呀,我们可以去看一下,它是一个偏移量啊。它在哪里赋值的呢?咱们有一个静态代码块,在这个里面也有一个title ofet,在这个里面也赋值的,也通过onafe,然后获取对象四段偏移量,获取4T是哪个偏移量啊。那就可以拿到了。那么这个on对象你千万不要尝试去操作它,因为这个对象啊,它只能在JDK的源码里面来使用。那么在我们的啊代码里面是用不了的哈。啊,无法去使用。OK,那么比如说他这个呢,直接ona.get ona注出来一个ona对象了,那这个get ona呀,它就相当一个call啊senitive。
16:09
加这个注解的只能JDK自己去使用啊,那我们的使用者呢,是无法去使用它的。当然呢,我们有各种方式啊,通过反射的方式是可以拿到的啊。但现在你拿到了,这也不建议你去使用它,你从类名就可以知道它是不安全的啊,最好呢,不要这样去操作,那么JDK呢,也不建议我们直接操作它啊。操他。好,那我们回到这里来,反正总之呢,一上来呢,就做一个CS操作啊,从零呢定性为一。如果三值是零。啊,视频在这个IQS里面还有一个set这个那个字段的啊,咱可以去看一下啊。还有一个死胎这么一个玩意儿。啊,在哪里呢?来找一下啊。是。啊,在这里呢,也是一个int类型的语义的。
17:01
啊,Int类型的。那对它进行零一操作啊,如果操作成功了,它会把当前线程记录下来,记录为排他容有者线程啊,哎,那么这个方法是哪里的呢?好,这个类啊,是咱AAQS的一个负类啊。好,咱可以去看一下。因为这个类呢,它的这个实线类啊,或者子类就是我们这个呃,AQ啊。那么这个类呢,就会比较复杂,比较简单了,没有我们IQS那么复杂,我们的IQS呢,有2000多行代码啊,但是这个类啊,很简单,它里面只有一个属性叫exclusive owner three。是一个线程对象,就是排他融有者线程互助面积,你也可以翻译,为啥呢?翻译为有所线程。好,那么它里面呢,还有这个有所线程的S和get法。那么我们这里呢,就调的是一个赛等法来记录我们的有所线有所线程啊。
18:05
那么下来呢,我们还要进行重录呢,比如说呢,我有一个线程,那么获取A的这样的一个进行A方法获取到锁了。那么紧接着他进入A里面的B方法,它也要获取锁,对吧?啊,如果这些在已经获取过锁了,就可以进行重入呀。那么我怎么知道这个进入B的这个线程,就是就是外面这个线程呢,就直接获取A的这个这个锁的线程呢。那咱去咱得要去判断啊,将来哈,他要把这个,他要把这个线程呢,给它记录下来。啊,如果啊,获取所成功的会再记录下来。啊,如果货理锁失败了怎么办呢?还有一个呃,快的方法,好,我们边说边给它记录下来,你打开一个编辑器。啊,首先呢,我们这个可重入锁的加锁啊。可重入锁的这个加锁的流程这样子的,首先呢,我们这个位置,当我去调用软lock里面这个lock方法的时候。
19:03
来看一下啊。到掉re enent lock里面的lock风华的时候,那它掉了谁呢?啊,它呢,又掉了我们的think里面的勒方法,而这个think呀,此时它是等于none fair think。是调的是none fair think里面的,那么lock方法调它里面这个lock方法。那刚才呢,我们已经看到这个lock方法了哈,给它拷贝过来,然后放到这个位置。放到啊这个位置。好,那么然后呢,它里面干了什么事情呢?咱可同入锁,加锁首先第一步。他开始通过CIS讲的是获取获取锁。那么如果没有人啊,没有现成。没有线程,那么占用这个符,那么也就是说呢,也就是T的值塞值等于零时,那么它CS呢,就可以获取到锁雷啊啊所加锁成功,这并记度。
20:13
咱的这个当前线程对吧,并记住当前线程,那么是有所线程啊。那么如果已经有人有锁了。那就获取锁失败呀。好,那我们来看啊,如果有人有锁的情况下,它会执行这个枯叶方法。哎,这个亏方法是什么方法呢?它是AQS里面的一个方法哈。好,他会执行我们AQS里面的。又调用这个AQS里面的这个。呃,Queer方法啊,OK,那么这个queer方法呢,不是我们自己实现的啊,那么aqs呢,已经帮他实现好了。那么这个方法咱可以看一下,这里面有两个操作,你看用按的符啊,给它关联起来的啊,有两个操作,一个是前面的有一个方法,那后面呢也有一个方法。
21:09
那么我们知道and符在Java里面,如果前面的返回值前面这个表达式的反义值是true的情况下。那么后面会怎么样呢?后面才会执行。后面才会执行,只有两个表达式都为出的情况下,它才会返回出啊。现在如果前面为to,后面才会执行,如果前面已经为false了,那么整个表达式就直接为false了,对吧?啊,所以呢,后面这个呢,就不再执行了啊。后面这个方案就不再执行了。所以前面这个方法呀,很重要。好,来看下这个亏。啊KK呢,你翻译过去常试或取所啊。那么下面这个呢,呃,Q。就是入队了啊。就入队了。好,我们可以看一下这个啊,这个方法。
22:00
那么拆Q的方法,你点进去你会发现。他这个方法呀,并没有什么实现,还只拗了一个性能异常抛出去了。哎,为什么会这样子呢?因为QS呀,其实它里面大量代码都帮他实,都帮他实现好了啊,你会发现这个类呢,有2000多行代码。大V代码已经帮他实现好了。那我们呢,可以基于IQS可以实现我们的独占所。独占所啊,那么也可以呢,基于他们来去实现我们的共享锁。共享锁,它可以实现这两类锁啊。好,那么咱具体实现的话呢,一定要重写它里面的这么几个方法。那么如果你要去实现独占所的话,我们需要去重写一个TRY,亏你try release方法。那么你也可以呢,实现我们的共享,所有aqui以及呢try release。好,那么实验这几个方法,这两个方法就可以实现共享所了哈,那么通过这两个方法可以实现。
23:03
啊,独占排他索。好,那我们的人称lock就是独占排查所了。所以呢,咱们就要重写TRY要要以及try release。那么这两个方法。那么China k,那么在这个think里面,哎,它到底有没有帮我们去实现呢?那么think呢,它实现了是继承了这个aqs啊,他有没有实现这两个法呢?那么咱们来看一下这个think啊。那么think里面,它放在实际上release。但是并没有帮我们去实现呢,是那个think那个此类啊。Think这个词类。因为这里面它只实现了release。那么亏,亏在哪里呢?吹啊吹啊。在我们的。Fair think里面。因为刚才呢,我们看到lock方法,None feel think里面的lock方法,那么它其实还有啥呢?还有这个TRY和方法。
24:03
那么也就是说呀,我们这个地方呢。咱的这个none fair think里面lock方法,调用了AQS里面的clear方法。那么这个方法又最终调用了。我们的,呃,No fair think里面的。然后呢,是TRY啊try re啊TRY要亏这个方法啊。出对法,那么有它得以实现加锁的。好,那么这个加速来看一下你它又调用了一个方法叫none fair trial方法,什么叫none fair tra方法哪里来的呢?也在none fair think里面只有这两个方法了啊,那这个方法呢,肯定是继承自父类的。好在这个sin的负类里面。他给咱定义了一个定义一个none fair que这样的一个方法,就这个方法啊。
25:00
啊,就这个方法。所以就就就就调这样的一个方法,因为它调到think里面的。啊,来看一下第二个think里面的,Think里面的用的是none。能非要TRY亏方法翻过就是非公平要尝试获体所得这么一个方法啊。啊调这个方法好,那我们来去看,那这个方法呢,其实就很重要了啊,来看一下,展开看一下,那这个值呢,其实是是几呢,是一啊。睡衣。啊,那么这个一是哪里传过来的呢。我们再再看看这个流程哈。那么人称lock里面它有一个lock方法啊。人称lock里面等,先把这些都全部给它收起来。原称lock,里面有个lock方法。啊,在哪里呢?在我们这里有个lock方法,它掉了think里面的lock方法,它掉了think里面的lock方法,本质是掉了no fair think里面的lock方法啊。
26:06
第二个什么none fair think里面的lock方法。那么然后呢,呃,这个烙腾法呀,又调用了一个。呃,亏的方法也传了一个一过去了。它调了这个AQS里面那个方法传了一个一过去了啊。然后呢,这个嗯,AQS里面的呃扩源方法,这是AQS里面的呃扩源方法又掉了什么吹啊扩方法,注意这个位置呢,是一个一,所以这个位置也是一个一啊吹要方法。那么这个treasure care方法是哪里定义的呢?是在这个none fair think里面有一个treasure care方法啊,那么在我们的这个嗯,Now we think里面有一个。啊推耳窥方法,注意这个地方是一个一传过来了啊。那他要调的什么?None fair trial clear none fair trial是think里面的,是这个think里面的一个方法,然后把一呢一直传递过来了。
27:09
所以呢,传递到这个no fair care这个方法里面,那么这个地方是一个一啊这个一,所以这个地方呢,也是一个。这都是一,他又弹了个一过来啊。他这是一个一好,那么在这个方法里面,我们来看他又干了什么事情啊。先去获取了当前线程three的点cut straight获取当前线程,让它获取T的值,那这值来看一下get STEM也返回值。好,那么来看啊,在这里面来判断代值是不是等于零。那如果等于零。那么他会干什么事情呢?来看来做了一个什么CS的操作。从零设置为一。啊,设置为一,如果设置成功了,那说明获取锁成功了,那就把当前线程记录为,当前这个线程记录为。
28:04
啊,有锁线程排它容有者线程就有锁线程嘛,那最后呢,加锁成功对啊。啊,如果sin值等于零。然后呢,开始去CS死了一会就锁了啊,那跟这个第一步的操作是一样的,又做了一次这样的一个操作啊,跟前面那一次是一样的。那么啊,然后呢,我们来看。呃,要干嘛呢?如果在值不等于零代值不等于零,它就做什么事情,判断这个当线线程。是不是这个,哎,排他仍有者先生,是不是有所先生。如果单线线程就是U酸线程,咱进行重入呀,于是呢,它会在这个C给C呢。加几呢,加了一个一,这不是那个一嘛,对吧,做了一个加一的操作。就每重录一次会加一,一次每重入一次呢会加一,每重一次会加一啊。哎,这样的。
29:00
好,那么然后呢,加一过了之后,这个SC是是S加一后的那个值啊,如果加一过之后呢,小于零,那抛出一个异常,那不能小于零啊,如果小于零你就抛出异常。如果不小于零,就把这个加一后的值就能赋值给这个斯泰那个塞特啊啊,就把这个加一后的这个新值呀,设置给S了。啊,这样子好,那我们继续回去要最后的加锁成功啊啊,重入成功,不管是加锁成功还是重入成功,都准成一个出啊。哎,否则呢,就加锁失败,返了一个false。好,那么这个位置呢,嗯,咱们这个位置啊,如果代值等于零。C值等于零,是不是没有线程有锁,是又尝试了一次呀,对吧,它这个地方呢,会会做两次这个操作啊两次操作。那么然后呢,来看啊,如果死拍的值,如果死派的值,那么不为零,那么说明说明所已经被。
30:13
被占用,那么则怎么样?则判断。当前线程,那么是否是当前线程占用的数?啊,是否是有所限成来,是不是一个单节线程占占用了所哎,如果是,那么则重入,哎,所有的重入呀,就对这个4T的值来进加一就可以了。OK,那么否则,如果以上都满足否则,那就加锁,加锁失败返回一个false。好,这是咱们这样的一个东西啊,加的失败怎么办呢。那么加速失败的时候,返回是一个false。加速成功或者重复成功都返回出啊。
31:00
那么回到我们的AQ里面去。啊,在我们这个iqs里面,哎,咱们不有这个库方法嘛,对吧?啊回到这个库方法,那么他自己的加锁成功的情况下。那它会返回,那返回。处加速成功或者重入成功的情况下,为处那加一个非,那不就是false了吗?那么是false的情况下,那后面就不用去执行了。那是如果加锁或者重入成功的情况下啊,或者重入成功的情况下,就不用去进行后面的了。啊,这个呢,也不用去执行了。如果加锁失败了,返回值是false,加一个非,那这块呢,不就是出了吗。所为处了,那么按呢,不的情况下,前面为处还不行,你要看看后面是否为一处,所以呢,后面呢就可以执行了啊。那么后面这个方法有一个什么呢?Ad外这个方法,这个方法才是我们的关键啊,来我们进去看一下。他首先呢会去扭一个nude。把当前线程给包装进去。
32:01
啊,然后呢,它这呢就会获取我们的这个OV啊,那么这是一个再有一个什么呢?有一个先进先出队列,那么这个先进先出队列啊,有一个he的就头节点哈,那么还有呢,还有这个呃,一些节点其他节点。那最后一个节点呢,想的是这个节点哈。尾节点,那每个节点里面都会封装一个线程。啊来获取锁的线程,每个节点里面都可以封装一个获取所的这样的一个线程啊,以及这个获取所的这个线程有一个S瑞的啊获取锁的线程。那么会到这个尾节点,普瑞的就长的就是这个尾节点。如果这个尾节点不等于那不等于那的情况下,那咱就把这个新节点呢,前一个指针这前一指针啊,前一个指针pro这个指针,那么指向等到五个节点。那么然后呢,在CS来设置尾节点。设置成功了,再把尾节点的是那个尾节点的下一个节点指向我们的这个新的节点。
33:05
好,那么也就是说呢,它每一个节点之间呢,都会有这样的一个关联性啊,那么指向上一个节点,这以及呢,被下一个被上一个节点指向当前这个节点啊。啊,这样子。啊,指向上一个节点,指向下一个节点的,指向上一个节点指向下一个节点的。啊,这样的一个双向链表,你可以认为。OK,好,那么这是咱们这个呃,CS,而且追加到这个最后面去啊。如果这个尾极点不等于空,就接到尾极点后面就可以了,那如果尾极点已经为空了呢,你这个如果为空呢,那这块就不走了呀。尾电为空的情况下,直接走这个了,走这个了啊一啊Q。那这个话干什么事情。来我们来看,如果尾节点为空了,如果我这个B列不为空的情况下,它至少会有一个节点,也有一个是此时应该是头节点是等于是尾节点的啊,如果有一个节点的情况下,头是这个节点,尾呢是也是这个节点呢,对啊。
34:05
那如果尾基带为空了。说明整个队列已经为空了。啊,比如说呢,我刚刚去啊,有一个呢,有一个a QS sta。啊,从来没有没有人获取过锁啊,突然第一个人来获取锁,对啊,获取锁,他占用这个锁了,那么又来了一个请求,然后要去获取锁。那么这个锁呢,已经被第一个线程给占用了,那么第二个线程怎么办呢?只能是入对啊,此时队列是为空的,那为空的情况下怎么办?啊,这个呢,就在做这件事情啊,好,我们来看一下,如果此队列为空怎么办。你要做了一个什么自选操作。那么首先呢,来去获取这个尾节点,若尾节点等于空,T呢,就等于尾节点吧,若尾节点等于空,来一个CS操作设置图节点,你有了一个空的节点,一般情况下这个节点里面啊,会有一个现成对象啊,你此时这个节点里面有现成对象吗?没有。
35:01
它它会你有一个没有现成的一个节点啊,你可以认为是一个空的落的节点,不带现成的啊。所以呢,咱投节点啊,总是一个空的,空的节点,你可以为是一个空的节点。啊,这头节点哈,你有一个空节点,作为一个头节点。好,那么然后呢,此时呀,尾节点呢,也等于这个he的头节点啊,尾节点呢,等于。He的投递点。那么然后呢,执行到这个位置呀,咱整个循环就执行完了,执行环之后呢,进入下一次循环,你要死循环吧,进入下一次循环。进入下一次循环之后,那么我这个T就拿到我们这的一个尾节点了,此时咱队列里面只有一个节点头,就是尾,拿到哪个尾节点了。G呢,等于为节点。人们把当前你new的这个节点,再把那个new的节点已经存进来了,它new了一个节点,这个节点呢,就是我们当前这个线程的啊,就那个第二个线程。
36:00
第二线程想要获取锁吗?获取失败了,入对了呀,对啊,入对了。那他把这个基点呢,追加到这个空气点后面去。那怎么做呢?它会把当前这个基顶的前指针,这个指针,那么指向我们这个T。指向我们这个空的尾节点啊,它是头也是尾啊,指向这个节点。那么然后呢,再去啊CS设置为设置完了,然后再把这个TT选的TV这尾节点吧,把这个尾节点的。Next指向我们当前这个节点。当前我们这个node节点。节点那么就可以了。那么现在的话呢,咱头还是这个空节点啊,那尾的话呢,变成我们这个no的新节点了啊。变成我们这个多的清节点了。还战略有关系,那最后呢,T就退出循环了,整个这个方法就已经结束了。他就对加到尾节点后面去了。啊,就这个意思来进行排队啊。
37:02
啊,那么也就是说呀,我们这个fio队列第一个节点其实总是一个空的节点啊。它是没有任何线程的指向的。啊,这是头节点,那么只有后面的这些节点从第二个开始,那么才是带现成的啊,才有这个瑞的第一个节点都是是一个空的。是功的不带线成的啊OK,好,那我们就是啊,咱们讲一个iqs这个方法啊,我们再回去。总算就开始入队了吗?好来加速呢,我们就看到这个位置就差不多了啊,因为咱这个1000多行咱不可能啊,2000多行,咱们可能每一行都去看一下,那简单的看一下啊,如果你要对它有更多理解啊,请关注我们上阴骨的相关专题啊,OK,那么否则加的失败,人们是入队等待啊,这是咱们这个啊枷锁。那么可重组的解锁什么样子的呢?好,我们来去回到这个lock里面去啊,它有这个应该有这个解锁方法。
38:01
那么解锁方法它就会必要think里面的release方法,然后传一个一进去。好,那么来看一下这是可重入锁的什么解锁流程?好,那当我们去调lock里面的。这个unlock方法可以解锁的时候,那么它会怎么样?它掉了,那么咱这个think里面的方法。那么这个think呀,我们知道咱前面给他赋过值,负的值是谁呢?在非公平所里面,负的只能是none fair。在这个none think里面有没有咱这个release方法呢?好,来看一下啊,在这个none fair think里面。只有lock方法,让只有含量,只有吹方法,并没有release方法。那么类似方法在哪里呢?你可以点进去看一看啊,那么这个话呢,也是aqs给我们提供的。
39:03
好,它AQS呢,给我们提了一个release方法啊,直调AQS里面的release方法,然后这个这是一个一啊传递过来的啊,写死的哈,在人称lock里面写死的。那么这个release的方法干什么事情,因为它用调上的调吹release,然后把这个一呢传给这个方法了。那类咱前面讲过。它对应谁呢?对应我们的是那个吹queer方法哈。分化是获取所得。那么release方法呢,是呃,解锁的哈。那我们的,呃,这个人称lock里面。Lock里面必然要去实现这个try release方法。那么不是非公平所能实现的。而谁呢,把这个think。这个负类容易实现的啊。啊,不管是none fair think,还是feel think,不管是非共性素还是共性素。
40:03
他们走的都是think里面的try release方法啊。来看一下。啊,它这里面呢,有它的一个拆流方法,这个流方法是释放锁,怎么释放锁的。大家读一下啊,首先呢来获取态的值。然后在它值的基础上来进行减一,就是那个一那个玩意儿啊。好,那么最终我们的AQS,它又会调用我们think里面的try release方法啊。Carry这个方法是think里面的。然后是方法。好,这个地方呢,它会给我们传一个传一个一在这个位置。好,那我们来看啊,它里面的这个业务操作什么样子的M1记录下来,首先呢,获取T,让减一后的这个值C。然后做了一个判断,判断,判断当前线程是不是排他有拥有者线程,是不是有所线程。
41:06
哎,如果单机线程不是有所线程说明什么。你不是要,那不就是要释放别人的所能吗?他说你这个锁都不属于你,结果你要去释放所,那说明啊,说明你在恶意释放所,所以就抛出这异常啊。OK,那么首先呢,他会做第一个判断。那么判断当前线程是否是?啊,有所有所建成。那么如果不是,则抛出抛出异常它是第一个,那么第二步啊,我们来看一下啊,那么接下来呢,他就看看这个减一后的值,C呢是减一后的值。这个啊,可重复锁啊,解锁的时候呢,每解一次锁,比如说呢,我这有个A方法,A方法呢,有这个加锁的方法,对啊加锁的方法,然后呢,这个有一个B方法,那B方法里面呢,它可能也有呢,也有这个lock加锁的方法啊,我就这样写了哈,然后还有什么unlock方法,进行完业务操作之后呢,由unlock方法来解锁。
42:12
那么然后呢,我们的这个A方法外面呢,又有一个N方法来解锁,对吧?啊解锁,那么第一次加锁的时候,那么S只能等于几呢?等于一对吧?啊,S等于一啊。等于一,然后第二次加速的时候呢,Sta它会加一,加一过之后呢,值呀,应该是等于二的啊。那么它解锁的时候呢,它会对S的值进行减一,减一过之后呢,对它值来进行减一操作。然后呢,再解一次的时候,又会减一次操作啊。那么如果减一后等于零说明什么?是不是又解完了呀。都出来玩了呀。那出来完了,那我们就可以把酸给释放掉了,你看free瑞呢,这个变量设置为出。那最后呢,来看塞,把排它有所线程,排它中有所线程,把有所线程设置为空。
43:04
哎,然后呢,把这个零设置给谁呢?设置给莱特。最后呢,反了一个处代表呢,释放所成功啊。好,那么来看,那么第二步呢,我们开始那对此T的值,那么减一减一,后来进行判断,减一减一之后。那么来去判断派的值,那么是否是否为零,那么为零,是啊,解锁成功,解锁成功,那么然后返回处啊。好,那么如果不为零呢?好,我们来看一下。如果为零,那么这个时候负A是为出的,返回是一个出。
44:00
然后把优质线程。给它设置为空了。好,那么然后呢,并且把这零呢设置给sta了,那么S一旦设置为零了,其他线程就可以获取锁了啊,通过CS来获取锁。那么如果减一过之后不等于零呢?直接把减一后的值设置个。啊,已经减一过了,是这个塔,只是没有减为零哈。让反比值上的反应值是false。好,那我们来看啊。呃,如果那么减一后的值为不为零不为零,那么怎么样呢?就直接返回,把减一负的值设置一个值之后呢,然后返回boss嘛。八减一负的值,然后咱就认为呢,是S值已经减一了。啊减一后不为零了,对吧?啊现在已经设置上去了啊,做到返回线的返回false,如果接锁成功返回处。啊,这样的。它这就最最想的就解锁那个业务操作了啊,当然后续呢,还有很多其他的操作,咱就不一一去看了,因为整个类呢太过于复杂了,咱的目的呢,是为了讲讲咱的这个分布式可重入算啊。
45:12
那只要了解相关的枷锁和解锁的基本流程就可以了。好,那我们就到这里。
我来说两句