00:00
那我们刚才呢,已经把这个问题抛出来了,看解决方法,解决方法呢,我提出了两个方法解决第一种。用全局变量加速来搞定它。就是用全局变量加速,什么意思呢?各位同学,咱们可以这么玩一把,听听我的这种思想啊。你现在的问题不就是因为,因为现在问题就是说。斜程一斜程二斜程三斜程四都有可能同时来操作map吗?其程问题就在这导致的吗?那我如果这样做呢?假设我在这有一把锁。假设我这有一把锁。当任何一个携程去操作我们这个空间时,先看这个锁有没有被关闭,如果它是被关闭的,那你就在这里进行一个等待,也就是说在这个地方我们对它做了一个处理。做了一个什么处理呢?让他排队。注意听这句话啊,让他排队就说我的这个概念就会发生一种变化,你现在不要那么猛。
01:04
大家看我把这个进行一个改进,我改进成这个样子了。好,我把它进行一个改进,往下拉。往下拉。好,接着往下继续拿。好,各位同学,我要对他进行一个改进,我改进成什么样子哈,首先我要加锁了,加锁呢,就意味着你们不要先来,先来到这来。好,你要你不是你学正一想来操作他吗?你们先来这儿持有这把锁。好好,当这个携程一正在操作这个锁的时候呢,他如果拿到这个锁,他就继续执行。他就直行往下直行。往下执行。它就可以往下执行。好,他执行完了过后呢,这边就解锁,他就解锁。他在这边就解锁。就unlock啊,这边我们叫做lock。
02:02
Lock。啊叫加速,这边操作完完毕过后就unlock。Unlock。Lo,好,当我正在操作的时候,比如说携程一正在操作这个数据空间的时候,假设他正在操作,而携程二又来的时候呢,他也先到这边去看目前这个锁是不是加上的,如果他发现。加锁了它怎么办呢?它应该把它扔到一个叫做队列里面去,队列缓冲,比如说这边会产生一个队列。各位,它这会产生一个队列。好,至于这个锐列是什么结构,其实就是个数据结构,那么我给他来一个变量,说哎,这个时候呢,携程一先到这来排队,携程一说,哎,我不着急,等你做完了我再说。啊,当然他就这这样子这样做的啊,他说哎,不着急,我我先等待,我等待,然后呢,他先把自己排到这,他说我携程一在这等待啊,邪神一。
03:04
啊,携程二携程二等待好,如果说携程三,因为携程他携程三他也傻乎乎的,他也在操作,但是他发现携程一还正在操作,于是呢,他也跑到这边说,哎,我也老老实实的在那排队。啊,我不跟你抢对吧?他也在这排队,于是乎呢,他就排到了携程二的屁股后边。啊,大家大家都按秩序来啊,七乘二就在这排队。携程二排队啊,携程三了,这个携程三排队,同样道理,携程四呢,也有可能排队,那携程是说,诶我也去操作,发现携程一有可能还正在操作,携程四也可能排队。先生是也可能排,以此类推,以此类推好,这样子呢,他们就有一个很好的机制了,什么机制呢?大家不着急,大家都按照顺序来玩。大家看到大家要其实就这样子的,同学们看,当携程一来操作者他先给这个map空间加一把锁,说诶同学们这个我我先等待你执行。那么携程二。
04:07
他发现有锁他就不操作,那么等到携程一执行完毕过后呢,他会把这个锁解开。解开,解开完了过后呢,它底层有有一种机制会从这个队列,其实这是这是这是个队列。他从这个队列里面呢,取出排在最前面这个携程让你去工作,这样子就好比。一个排队上厕所对吧,就就很形象的一个案例,说我们班有个同学张三。去上厕所了,这个厕所呢,只有一个坑啊,当然很惨,只有一个坑,他去了过后呢,诶,我先把门关上,哎,这个时候诶小明来了,他发现那个地方那个门是关上的,他就那肯定不能冲进去啊,人家人家正在这解决问题,你看冲进去太太没礼貌了吗?所以他就在那排队,哎,这个时候呢,李四又来,李四说诶,我怎么你们这干什么,我在排队呢,那李四肯定要讲道理嘛,说诶,那我就排在张三的屁股后边,好,这个时候王五又来了,王五说那那我也排在李师傅边,我排好排好了过后对不对?
05:10
哎,第一个人去的班长,他解决问题了,解决问题他他门诶一开口说,哎,你你进去吧,走了,那这个人呢,就开始进到这边,他进去的时候,他是不是也得也得把门锁上了,要是别人冲进来怎么办?所以他要把锁锁上,锁上那个斜成山呢,往上顶下,以此类推,那这样子就不会出现什么问题呢,一个坑同时有几个人在上。那这个就非常恐怖了,所以这样就解决问题了,来这个是一个形象的说明,那么代码怎么实现呢?怎么加锁呢?各位他的观点就是全局变量加速。全局变量个数,那么看到因为没有全局变量最佳锁,因此会出现这个资源争夺问题,代码会出现错误提示,这个这个解决方案我们加入这个互斥锁就可以了,加入互斥锁,那加入这个互斥锁的时候啊,我们来看这个方案怎么写。
06:06
它非常简单,就说这个地方我们先创建一个lock。创建一个lock,这个lock呢,在它执行的时候啊,在它进行执行的时候呢,我们来一个加速啊加速诶这个加锁是在这个地方加的,应该是在写的地方加锁啊,这读的地方其实加不加到也问题不大,但加一个也也也可以啊,加加一个也可以,那么我们看这个lock这个包包在什么地方啊,我们来看这个包。啊,这个包呢,是在这有个叫SYNC啊SYC,我们把这个包找到。找到SNC找一个。SYNC这个包。SC这个单词翻译过来叫synchronized synchronized呢就叫同步的意思,同步的意思好,大家看这里面是干什么的啊,各位同学跟上我的思路,他说centralize这个包提供了基本同步的单元,如互次所如互次所好,那这个呢还是不错的啊啊,那么他说这个是适用于低水平的程序员的线程。
07:15
啊,低水平就是比较弱嘛,对吧,他说呢,高水平的呢,同步应该是用channel说老师那个你们我们先来一个高水平的,我们先低再高啊有有时候你简单一点的,有一个全局呢,也还可以对吧,那通讯我们肯定会讲的啊,同学我们会讲,但是呢,我们不着急来,我们先来搞一个这个东西,同学们跟上思路,那既然是全局变量,那不啰嗦了,上来过后先搞一个东西,对在这啊。定义或者声明,一个声明一个全局的互斥所,互斥所看看东西啊,怎么写,各位朋友lock变量随意,然后它的类型是。ci.new text啊new text,那我做一个简单介介绍啊,同学们看,这个lock是一个全局变量,是一个全局的互斥锁。
08:14
护次所。那么互斥锁就说呃,我用了你就你就不能用啊,就叫叫互斥锁,其实还有一种锁叫毒锁,有毒锁和解毒和写两种锁,这个这个是互斥锁,属于属于这个斜锁,那么呃,这是第一个第一点第二点呢,这个syn注意听讲哈,这个syn全称。这个syn是一个包,是一个包,它表示什么呢?它是一个包,呃,它是同步的意思,然后全身是synchronized ync。那子的。SI好像这样写的,Size同步的意思。同步。还有一个单词叫做MU text text这个单词呢,是互斥的意思。
09:05
是互斥啊,比如说这样这么一个概念,那么我们看看是不是有这个东西,打开手册,我们看到里面确实有一个啊,有一个这个东西,大家看MU text,嗯,啊MU text啊,对,就它就它这个这个MU text呢,里面它是它是一个结构体,看清楚了啊,结构体里面有两个非常重要的方法,一个叫knock,一个叫。Unlock,那么lock是什么意思呢?Lock方法锁住M锁,给它加上,如果M已经杀锁,则阻塞,直到M解锁。unlock是什么意思呢?是解锁,OK,那现在既然如此,那就不啰嗦了,同学们那就拿到这个东西。咱们在这儿加。加锁。在执行之前我不管你那个现在加锁。这就好比什么呢?好比诶,就是你上厕所之前,你来先把门小门给他扣上对不对,那就lock。
10:04
第二。Lock。没问题,那你写完了过后你不你你你不要忘了啊,你还要解锁。那你要不结束人家?人家一直在那等着,比如说班长上完厕所过后,他从小门跑了,对不对,那那边那个门他没开,那完蛋了,这诶这这个人怎么老不出来哦对不对,那人家就憋憋憋坏了,那就出问题,那憋坏了怎么办呢?也有可能有超时,有些系统会这样子做,他发现在这等了,等等久了,等了60秒,那实在不行了,那人不能被被别人他可能,诶我在这个楼上去啊,楼上有可能还有位置对不对,人家这个携程等久了也有可能会直接就抛弃了,就我就不玩了啊也有可能。好,就看你的实际情况,你看我们那个网页,你看那个网页啊,访问一个网站一般来讲60秒,60秒过后,如果还没有网页返回,直接就是么样超时对不对啊,就所以说这个呢,我们也有这个机制,lock.unlock。
11:03
好,各位朋友,那这个一加进去我们看,呃,这地方为什么没有写。没包包。SYCSYNC,各位好,我们把它写进去了啊,写进去看有没有报错,没有报错再来玩一把,各位同学走,先来看啊,同样我们先来进行一个编译,看看还有没有这个数据的竞争。编译成功来跑一个main。命点够啊,走,跑起来,等待。同学,看这个时候其实他已然就没有什么呀,没有报错了,看到没有,他已然没,为什么没有出结果,因为我等十秒钟吧。好。怎么?怎么还有精准错误呢?那说明这个还是没有彻底的解决是吧?那有可能这个这种这种竞争错误是在这儿产生的,在读的地方产生的,在这再加一下。呃,我待会再解释为什么啊,这个理解起来有一点难度,应该是可能是这个地方导导致的一个竞争,那么我在这也加速。
12:07
Lock。Lock点。呃,Lock,先锁一下lock。好,然后呢,再解锁。在解锁。好,Unlock。Bo。好,我们再看看这个地方有没有问题,这全局的这地方是加了锁了。写的时候我加了锁了。然后这一读的时候,我也加了锁了。再来玩一把。好编译。哦,变异。好,编译完了过后我们再跑一下。OK,有问题没有,完全没问题了,好,这个地方有点不好理解的地方有两点啊,同学们,我相信同学们有几几个地方有点不好理解了。
13:08
第一个呃,第一个问题啊,同学们看到第一个问题,呃,就是为什么刚才呃,刚才就是说我没有在这地方加锁,它也会出现这个数据的这个竞争呢。哎,按理说啊,同学们看同学们,刚才其实我这已经已已经有个说明,大家看这里红框部分,这里有一个问题呢,需要给大家伙解释清楚,什么意思呢,就看这里啊。为什么这个地方也要加速?按理说我们已经把数据都写进去了嘛,那你读的时候那不加锁也无所谓呀。对不对,因为这个携程都已经不在了,它是这样子的,同学们,红框的部分就在遍利这个便利这个这个map map的时候啊,遍利这个map的时候,那么为什么需要加护士锁呢?按理说十秒十秒钟后上面的携程都应该。
14:05
全部执行完毕。那也就是说不会再有人往里面写东西了,后面就不应该再出现资源竞争的问题,但在实际行动中,在实际运行中还是可能在红框部分出现这个地方加加上出现问题,因为我们程序从设计上可以知道,十秒之后就执行完所有的携程,就是我们自己程序员是知道的啊,我们自个诶我们看诶十秒钟肯定做完了,但是但是啊,主线程它是被不知道的。主先生是不知道的,因此呢,底层仍然可能出现资源争夺,因此在这里也要加入扶持。就我们自己是知道的,但但底层那个线人,他可不知道你等了多久。这个他并不知道,他有,所以说他可能是他在里面做了一个处理,说,诶有可能你是不是还有人呢,他自己在那读的时候,他有可能出现一个志愿的一个震动,这个我不好解释啊,大家可以体会一下,就好比这样子吧,就比如说。
15:04
这个。这个有一个人上厕所上完了对吧,上完了。上完了过后呢,按理说上完了,但是有一个人进去过,他看见有人曾经在那排过队。他他就习惯性在那再等一会儿啊,这这也有可能不能冲进去就做,他可能还敲敲门啊什么的,那也算是个资源嘛,所以说这个呢,我们就要说一个是从这个设计层面,一个是从这个底层主先生他看不到的,他并不知道你休眠十秒钟还是休眠三秒钟不知道,所以他可能会去尝试着去尝试着去这个进行一个测试啊,或者去看看锁还在不在啊等等,那个也就叫资源的一种竞争,好,所以说呢,我们在这儿加入了这个东西过后,你会发现没有资源竞争了,这是第一个问题,我解释清楚了,第二个问题大家更觉得郁闷了,说老师你在写的东西我有点看不懂了呀。有问题啊。还说说老师,你这写的麦普185怎么是接成是零呢?
16:03
你们,你们有没有发现MAP185是是零呢?不对呀,卖这个185的阶层肯定不是零,不,不可能是零啊。而且而且说老师你也你也写的很清楚,这地方你等了十秒钟,那十秒钟肯定把这20个全部算下来,这个没有怀疑的。那为什么说你等了十秒钟还不行,我告诉你啊,你不要说等十秒,你就等你等1000秒,他还是零。只是我不敢设置。我等1000秒,我告诉你打出来,还是你知道为什么吗?这里面有一个问题,同学们。我们这个数各位同学,我在这地方存放的各位朋友,大家看到我这个map,我这个map是什么类型,Int类型,大家知不知道一个int最大能够存放的数是多大。我们这个int在我这儿是多少位的同学们?六六十四位的是64还是32位啊。六十四六十四的话,我这个是无有符号还是无符号的,有符号的最大是不是二的六十三次方减一啊。
17:07
六的23方,六的二三次方减一,你看一下最大数是多大?各位同学,六的二十三次方减一,你算二的六十三次方。减掉一个一。是不是就这么大呀?哎,我是六十六十特四还是八个八个字节,八个字节的,那么你看这个实际上是你你最大就存不进去了,说实话你看啊,我们看最大是哪个数,它很稳定,应该是66 66的阶层,我们看一下。同学们看啊,这45,这65,看各位同学请看,这已经是出现一个负数了,这怎么跑了一个负数出来呀。改成64个负数。这样应该已然越界了。你看这个数啊,我们看63有没有意见。
18:03
啊。上市。哪个地方见了?他这个这个都变成负数了,就说你已经再往里面存没什么意义了,再越界就变零了,说白了。怎么阶层它不是二的阶层,它是二乘三哦,它不是二阶层的,它是那个它是那个,那个是它是要比二要乘二阶层要大。对,我知道它是一乘以二乘以三乘以四乘以五,这个很快。很快很快,但是最大我们这个数量能存的是不是就这么大呀,那这么大你你去算一下,我们可以简单算一下是是多大到这儿啊,我们可以可以是可以简单的估算一下,我们可以简单估算一下,其实这个速度长得是特别特别快的,也就是说其实到。可能到30的阶乘早就超过它了,我们可以简单算一下是大概是多少,到这了,我们我这个很快一乘以二。
19:04
存三存四。陈武。乘六,哎,这还可以啊,乘乘乘乘六。成他有阶层吗?这有是吧,好的,那七的阶层。也没多少啊。啊,大家再听一下这个十十二的阶层。好,也也不算很大,我们看这个20的阶层。哦,你看20阶层就这么大,你早就存不进去了,都说这个原因是这样子的啊,就是不是我们的代码写出你20阶层,你看这个数早就这这很庞大一个数,你就别说其他了,你你来个30的阶层,你看这个数就就根本没法玩了都。都充不进去了,所以说我们这地方的问题呢,呃,已经不是资源问题,而是它存不进去了,所以说如果我们把这个数存小一点,它其实这个问题就没没没问题了,大家看啊,如果我把这个地方稍微调小一点。
20:02
调小一点,这个问题就没有了,比如说我带个20的健身。20的阶你看啊,基本上就没毛病走。走一个好,我们看效果啊,如果是20的阶层的话。哦,对,我没build,那就直接build一下。Build一下啊,来看may跑代码。啊,其实我们没有必要等,等十秒钟。也就是应该是两三秒就出来了啊,因为数据不大了。看啊。那我看现在资源的竞争应该还是没有。好,数据应该出来了。嗯,死机了是吗?哎,十秒钟应该早就过了呀。这个地方为什么出现这个恐怖的现象?我该做什么事了?
21:01
好,我把这个时间缩小一点,这个时间缩小一点啊哦,哎呀,我天呐,1000秒哎,等你等到黄花菜都来了,给他五秒钟吧,五秒钟应该足足的够了啊。五秒的是,怎么等这么久啊?对不对,12345应该差不多了,出来了。好,学们看,同学们看,这个是没没没问题的,你看到20多岁已经这么大了,对吧,没有没有没问题,代码是正确的,好那同学们现在呢,我们已然解决了,就是我们说到这呢,我们已经用全局变量加速对它进行了个改进,而且呢,我把各方面都介绍清楚了,包括为什么这加lock,以及刚才为什么返回这个零的问题,好那么这个讲完了以后,同学们知道了,下一步呢,我们就要用这个管道去解决,因为你虽然用全局变量加锁解决了,但是问题也很严重,这里面最严重或最尴尬的问题是这你到底等多少秒,你等五秒,等十秒都不合适,对吧?那必须要有一个新的方方法来解决好的,我先把它反述一下。
22:08
那刚才呢,我们提出了一个解决方法。对,我们提出了一个解决方法。好,对它进行一个板书,刚才呢,老师讲了这样一个东西。好。管道的一个基本介绍里面提出了不同这一个gro之间的一个通讯机制。好通讯机制是什么样子的?来一个标题三。那我讲什么了呢?我在这里提出了有两种方式解决,第一种呢,可以使用全局变量加速。全局变量的互斥锁,互斥锁解决,第二个呢,就是使用这个管道管道,管道就是我们的参楼来解决。来解决。好,这是两点,那具体来说呢,我们先用的是什么呢?使用全局变量。
23:00
家属来解决这个程序的一个什么呀,同步的问题啊,同步的问题,那这门标题三具体来说我怎么做的呢?诶具体来说我是这么做的啊,具体来说我这么做的。对,就在中说那代码的改进,代码改进怎么体现出来的啊,代码是要改进的,代码的改进为这样子代码。代码改进。改进。个矮改改进啊,改进核心的地方,我给它拎出来哪里呢?第一个我们在这加了一个互斥的。我们增加了一个互斥的这么一个锁。这是第一个地方的改进,是个全局的。好,这方我加到这里来了,第二个核心的位置,第二个核心的位置我在这个地方加锁了。因为你这个gro在运行的时候呢,你产生了很多的这个这个携程,那在这我们做了一个加速的处理解决了,好这是第二点解决了第三点,第三点呢,我们发现在还有一个地方也得加锁,就在读的时候,那读的时候呢,为什么要加,就是因为底层他并不知道你的问题,你的携程都已经解决了,所以说这帮也得加锁,不然的话呢,仍然会出现这个资源竞争的这种这种提示啊。
24:25
呃,但是这个资源竞争可能也不影响你什么啊,他可能就提示个信息而已啊,只示信息而已,好,那第一个方案我们就讲完了。
我来说两句