00:00
好,我们来去看一下是不是可以重入来,我们这是一个可重入所,那能不能重入呢?我们来去写一个方法,来一个public void啊,Test的方法。那么这个方法呢,我们也再次获取一下这个分不是锁啊,来一个类似点,Did she build lock clean,点上get lock,那么锁的名称咱们一定要一样啊,我会同一把锁。那同一个请求在获取同一八伏的时候,反应该是可以重入的啊,那反应只能是lock那个lock点上,可是lock方法A加速。然后是lock点上unlock的一个解锁,那我这种解锁呢,我就不放在final里面去了啊,我就随便写一下。那在这个中间呢,咱可以随便写点什么东西,比如就写个打印来去测试,可重入可重入锁。啊,那么咱这个方法写好之后呀,那我可以再减库存这个方法里面来去调一下我们这个雷似D,然后PA的方法。
01:03
那我们这个减库存就相当于是A方法啊A方法,那我们这个太子方法就相当于B方法。那么A方法它获取过锁了,那B方法里面又获取一次锁。那么同一个线程的情况下,我们应该是可以重入的啊,那么现在能不能重入呢?我们可以打一个断点去试一下,那我们呢,在这个A的加锁方法这个位置带个断点。那把这一块呢,咱其实可以收起来啊,那在B方法太子方法是我们B方法啊,打一个断点,那在解锁的时候呢,再打个断点啊。然后呢,在我们的内部这个B方法相当于B方法,那打个端点,加锁的时候打个端点哈,然后呢,是解锁的时候打个端点,中间再打个端点。好打好这几个特点之后呢,我们来去,呃,Debug重启一下啊,来debug重启。
02:02
好,重启呢,已经成功了,那我来去刷新一下这个页面。那么一刷新,我们来去看一下啊,首先呢,是这个A方法题题开始加锁了嘛,那我们来去啊走。啊,第一次呢,它运行起来呀,会比较慢啊。后续我们再测试呢,其实没有这么慢了啊,这已经获取锁应该是成功了啊,来看一下我们这个锁啊,已经获取锁成功了,还有25秒,然后我们来去呃,走走走到我们的这个下一个断点F9走到这个B方法这个位置了。然后呢,进入这个B方法里面开始加锁了,大家一起走怎么样下一步。他现在开始获取内部的唢呐。内部的锁能不能获取到呢?你外部的锁还剩六秒,六秒钟到了之后。哎,那它才进入内部,才进入这个内层的这个锁啊。
03:02
它等于外部的所释放了,哎,那内存所存进去。那如果外层锁没有释放,内层所能进去吗?进不去?哎,那他做了可重入了吗?就没有做到啊。为什么没有做到可重入呢?那么是因为啊,我们的UID导致的啊。那么UID在什么时候生成的呢?啊,在我们去get啊,在我们去get我们的可同入锁的时候。Get一个ready锁的时候,它就会调我们的构导方法来去获取一个ready分布式锁。在这构造方法里面,我们就会去生成一个UUID。那也就是说,我每次去get这个锁的时候,它就会重新生成一个UID。啊,UID的话呢,咱是为线程的生成的一个唯一标识哈,那么UID不一样,我们就认为呢,不是一个线程了。那么大家回到这个分布所里面去,来看一下啊,咱怎么用的。
04:03
我们在外层的这个A方法里面,就相当于我们的A方法里面。那我们就get了一次。那么此时它会生成一个UUID。OK,那么在内层这个B方法里面,那我们呢,也许get了一次,那么此时呢,它也会生成一个什么新的UID。那两个UID呢,他认为是两个线程了。所以呢,我们必须得要保证我们的UID呢,必须得是一样的,那同一个线程必须得是一样的。那怎么做到一样呢?OK,咱其实呢,可以这样子,那有同学老师咱为什么不使用那个线程ID呢。因为之前的话呢,我们一直在使用UID作为现象的唯一标识。每一次我们都会生成一个UID啊,那如果我直接去使用现成的这个ID,那不就一样了吗?那我们知道每个线程都有一个维达ID这样的一个东西啊,它就是线程的唯一标识了。那使用它就不会有我们刚才那个困扰了啊。
05:03
那为什么咱不使用它呢?因为在分布式项目里面哈,比如说咱此时的ID,我们都知道它会从什么,都是1234这些东西啊,12345类东西。啊,移植到几十个对吧,啊这样子。那如果这样的话,那比如在这个服务器内部,我们可能会有1234,编号是1234这个线程,那么在我们的这台服务里面也可能会有编号是1234啊,这这些线程啊。40大于D为1234这个线程。那么就有可能会冲突。啊,都不是一个服务的请求,结果呢,他认为是同一个请求了。那就守住了呀。虽然你不能单独的去使用S瑞的ID这样一个玩意,那么使用UID的话呢,好像也不行。因为他每次初始化的时候会给我生成一个UID。那咋办呢啊,咱可以两者结合。
06:00
那比如说呢,我可以给每个服务去生成一个UIID,而这个服务一启动的时候就生成一个UID,那么这个服务呢,我一动的时候也生成一个UUID。然后再去结合呢,结合现成的ID。那么只要你的UID不一样。那么UID不一样,那么里面的线程呢?内部每个线程的ID也不一样啊。那就可以保证我们的唯一性了。每个线程的一个唯一性了。那每一个线程咱的十大ID都是一样的啊,在在这个同一个服务里面啊,那不同服务的。不能服务的,那线程肯定线程的唯一标识肯定就不一样,应该是UUID加上内部的线程ID来做标识的。那使用它就可以完美解决。那我们现在呢,是每一个请求生成了每一个get log方法生成了,生成了一个UID啊。那么怎样才能做到每一个服务?
07:02
就生成一个UID呢,咱可以这样的啊。那我们这个分布式锁工厂,可令他这个工厂这个类呢,它是一个单立模式的。它默认就是个单立模式的。当我们的服务一启动的时候,它就会扫描这个注解所在的类,给我们初始化一个单立对象啊。单位对象。单位对象。那么既然是单位对象。那么如果我再给这个属性指定一个UID的话啊,给这个对象制定一个UID的话。对象是单离的。那里对象里面的这个UID属性。那么肯定也只有一个UID。那就是单立的了。那每个服务的原理都是一样的了。那么写法是这样子的啊,那我们知道这个注解啊,它默认会调用无参数导法给我们去初始化一个对象啊。注解的默认会掉无三个方法。
08:01
那你给它添加一个无参购导法啊,这应该是一个无参的,然后在这个里面呢。我就可以去给它生成一个string类型的一个ID。那么这个UID呢?再给他复一下值哈,是Z4.uid,那么等于让u id.random u ID点图子规。那么咱这样写之后呢,由于它是。单立的啊,那么它里面这个UID呢,在我们这个单立对象初始化的时候就已经指定好了,现在这个UID呢,只要是同一个服务,它一定是一样的。那么之前呢,我们在这个分布式所对象里面的一个初始化的,每次呢,我们就get的时候,它就会出现一个分布式所对象,那这是一个多立对象啊。每一次出差的时候呢,都会生成一个UID,每一次出差的时候都会生成一个UID。那导致呢,我们每一个每一个每一次获取的时候都不一样了,即使同一个线程也不一样了。
09:05
好,那么这样改造完之后呢,这个UID是单一的UID,我可以传递给这个内部的分布式所这个对象啊。好,通过咱们这个方法传递过去,来一个UID啊传递到。咱这个里面去啊,粘到非公制所这个对象里面去。那么这个UID呢,我们来看,嗯,咱应该有一个UID这样的一个东西啊,诶这怎么给我们起名字起的不对啊。那这应该是一个呃,Lock name,那这应该是一个UUID啊,然后我们这个地方呢,就不应该再重新生成一个UID了。他应该使用外部传递过来这个UID。每次都是一样的。那么这个地方呢,咱也不能单独直接去使用UID,因为只要是一个服务,它的UID呢,是一定是一样的啊。那么咱应该是一个线头。一个唯一标识,这是现成的唯一标识。那么线性的为标识啊,它可以碰装一个方法啊,来一个public,或者就直接返回一个视频类型的get啊,是现唯一标识这样一个东西,Get ID这个东西,那可以去retain,然是UUID,那么加上我们这个冒号,再加上一个read的点上看瑞,点上get ID,加上当前线程的唯一标识。
10:24
UID是服务的唯一标识,你可以认为现在是服务的唯一标识了啊,那服务内部每个线程的唯一标识,我这个加上去,那就可以防止呢,分布式服务带来的冲突性问题了,好,那么这里呢,啊是给那么线程来去拼接。拼接那么唯一标识啊,那么下来呢,我这个UID这个位置啊,应该给他用get ID这个方法给它替换掉就行了啊。来拷贝一下,拷背好之后呢,那下面这个位置呢,也是一样粘贴进去。
11:01
好,那么这样呢,我们就。搞定了啊,那么呃,这样改造好之后,我们再来去测试一下,看看能不能做到可重入呢啊。好,咱们来去重新啊启动一下这两个服务。啊,我们断点呢,应该都打的好好的啊,好好的啊,那么现在呢,我只要是同一个服务,那么咱这个UID是一样的,只是呢,背后呢,我们又拼接了一个现成的ID。好,来看这个最终效果,启动已经启动好了,那么启动好之后呢,我们可以去发送一下这个请求,来已经进来了,建中了,直接F9让加锁,应该是已经成功了,进入这个内部方法,还没有进入来啊,走到内部方法了,来看这个拉锁。也已经有了哈,因为它会加一个现成的唯一标识。然后重入了一次过期时间还有24秒,应该没有了啊,还有16秒,赶紧的进入到内存这个方法开始进行加锁,F8,下一步你已经加锁成功,那么此时呢,我的锁值应该变成二了,你这个呢,依然是31,过期时间已经重置了啊。
12:06
啊,那么说明咱已经可以做到可程度了,那赶紧去解锁轴,可以解锁一次。那解锁完一次,第二次呢,A的这个方法还没有解锁呢啊,解锁一次才减一,你还剩一个,那再去解锁ZF9,它就全部出来了啊,这个锁呢就没有了。你刚才有11秒呢。那现在呢,就已经没有了。好,那我们这个可投入呢,我们就已经做到了,做到可投入的情况下,那我们还得要去试一试,在高并发情况下会不会有问题啊,刚才呢,我们改动了一些代码。它还能不能保证我们的病房安全问题?啊,咱把这些端点呢,全部给它去掉啊,不要干扰我们啊,然后这个考重入锁这个位置呀,我们也给它去掉啊,不要干扰我们。那么上面呢,还有一个断点,我们也给它去掉。那么接下来呢,我们来去,呃,让啊重新启动一下。
13:04
好启动好之后呢,我们还是在页面上去刷新几下啊啊,它会预热,因为前两项呢,它会在这里就刷新。因为呢,在我们服务刚刚启动的时候呀,很多懒加载的资源并没有加载好。那么前两次访问,它会对我们两个服务内部的懒加载内容进行加载。那么访问成功之后呢,那代表呢,他已经预热好了,我们需要这样预热一下,以免影响我们的测试性能。好,那么回到RA里面去,咱们把库存数量改到5000件库存啊,来保存一下,那保定好之后呢,我们也找到压力测试工具来看看它,它的性能怎么样啊啊,能不能保证现场安全啊,我们来去运行。那么此时呢,他应该也是600多的这种并发量啊。嗯,好来看啊,稍有提升。因为之前呢,我们是每个线型生成一个,生成一个UID。
14:01
那么现在的我是每个服务就会生成一个UID。那么UID的生成啊,它本身呢,也会浪费一部分性能啊,那么此时呢,性能会略有提升。好,那么然后呢,回到咱们的RA里面去,来看我们的库存数量啊,也已经减为零了,那说明呢,它可以保证我们的可重入性,又可以保证我们的现场安全。好,那我们的可重入分布式所呢,我们就已经成功实现了。
我来说两句