00:00
前面我们给大家说了一下lock这个最常见的锁,以及lock我们来指定过期时间的锁,包括呢,还有更高级的,比如我们还可以使用try lock,这个try lock跟这个lock的区别就在于我们这个lock啊,它是一个在这无限等待的阻塞方法,比方说我们只有获得的锁了以后,我们就会来执行业务代码,但我们却可以来调用穿lo,我们可以来指定我们最多等待多长时间,那前面的时间呢,就是我们最多等待,我们最多呢等待获取锁100秒,如果100秒后呢,还没获取到,那就算了,而且呢,我们在加锁成功以后,比如我们这个100秒之内,或者100秒之后,我们获取到了,我们这儿就会返回处,否则就会返回false,我们就可以来判断if处,那获取成功了,我们就来执行业务代码,最终解锁等等等等,这个东西呢,大家也可以在下边测试一下,包括呢,我们这个reddi也可以实现,我们称为叫公平锁,那所谓的公平锁就是。
01:00
是大家在抢占所的呢,是有顺序的,比如我们1万个请求,他有顺序进来抢占所,那如果是第一个占到了所,他释放了,那就应该是下一个来占锁的请求直接交给他,而我默认呢,是非公平锁,那么这1万个请求,只要锁一释放,大家都来抢的,所以呢,我们这个red也可以来实现公屏锁,公屏锁呢,那就是换一个方法,Get fire lock,我们获取公屏锁就行了,剩下的呢,与之前的使用方法都一模一样,大家可以看一下就行。那么着重的给大家再来演示一个锁,叫读写锁。这读写锁呢,我们来直接给大家给一个场景,包括读解锁,我们也是使用red,直接点一个get read write lock,获取一个读写锁,然后这个锁名一样,那就是同一把读写锁,然后呢,我们以后业务要读的时候,我们就来加读锁,业务修改数据的时候呢,就来加写索,我能实现一个什么效果?如果别人呢,正在修改数据,我们还想读取到最新数据,那么就必须等待别人把这个写索释放了,我们这个读取数据才能进行,但如果大家都是并发毒。
02:12
那互不影响并发血呢,肯定得一一排队,所以毒邪索呢,它总是成对出现的,邪索控制了毒索,只要邪索存在,我们毒锁就得等待,包括鞋锁跟它自己本身也得等待,挨个释放以后再来执行,如果鞋锁不存在,我们毒锁呢,一直在这使用,加锁跟没加是一样的,跟我们GC里面的读写锁也都一样,包括使用的办法,我们加锁也可以给它设置自动时间,也可以使用默认的,这都是一样的,来给大家测试一个这个读写锁,比如我们还是在我们这个index上,我们来写一个简单的请求,来public,来写一个string,我们就来write一个value,我们就来保存一个值,这个值呢,我们假设来我来写一个get map给我们来发送请求,好,我们就叫get满发送请求,这个发送请求呢,我们比如就叫right,我们来发送一个叫right请求,然后呢,如果我们这个值写成功了,我们就把写。
03:13
成功的值我们来返回出去,那我们写的这个值呢,我们就直接模拟使用UUID就行了,U u ID random u u ID to string,我们假设呢,业务会给我们产生一个值,我们最终呢,把这个值返回出去,但是呢,由于我们是一个并发,我们好多人呢,都可能读取到这个值,如果这个值正在修改的时候,那别人呢,就等一下,我们最新的值改完了以后,它才能读,所以为了模拟我们这个程序运行嘛,我们还是thread sleep,我们等上30秒以后,我们再来给它算是写成功,好来假设呢,在这要写一条数据得等30秒,好,我们在这呢,给它surround with try catch,这是我们的业务逻辑。这是我们有一个请求是来写数据,好,我们来放在这儿,这个请求呢是来写数据,同样呢,别人可能会发请求来读取我们这个数据,当然这个写数据呢,我们可以把我们这个数据保存到一个地方,比如我们也保存到red里边,好我们要操作red,我们就把string red templilet string,我们这个red templatet来注入过来,Red templatet,好来写一个owa。
04:27
好,我们现在呢,准备给red里边,我们生成了一个UUID模拟,模拟业务超长完了以后呢,我们把它放到red里边,我们来set,给red里边就保存一个K,比如这个K呢,我们就叫right value,我们写的这个值,值是多少呢?我们把这个UUID存在这现在我们给red里边存在一个值,那接下来就有一个读方法,我们要获取这个值,那我们都给每一个加上response body,好,包括我们来再来加一个读方法,我们专门来读取值的,我们这个呢是写值的,我们把这个读取值在这来写上啊。
05:04
Response body来也加上response body,那么读取值呢,就简单,我们也不用模拟了,什么业务超长,我们就在red里边,我们直接来获取值就行了,我们option for value,原来呢,Set的是这个值,那我现在呢,就get,把这个值重新拿出来,给我们一返回走,那返回出呢,就是这个S字符串,这个S字符串呢,最终我们写出去就行了,我们这也没有这种异常,我们就来直接整一个这个异常,这是我们这个简单业务,每一个人的业务都简单,这个业务是写,这个业务呢是来读,但是如果我们来加了读写锁,我们来看一下,诶我们这一块呢,叫瑞Bo body。就是我写数据的时候,我们来加写索,记住读写索的用法就是改数据,改数据加写索,然后呢读数据加读索,那我们来测试一下,我们使用red来,我们有一个方法叫get,有一个read right look来,只要是同一把锁,我们就叫read right look,好,我们锁名呢,只要是一样的来看我们先来获取到一个这个锁,然后呢,这个锁我们要加鞋锁,怎么加,我们通过它,它呢有一个叫right look,我们拿到它的鞋锁,这是我们拿到了它的写锁,然后呢,它的这个写锁我们来给它调用lock方法,相当于加锁,那加锁成功,我们来把业务代码整个值都改了以后,我们最终结束了以后,我们来给它释放这个写锁,点一个onlo,我们把这个写锁呢放到最外边,我们只要加锁成功。
06:46
我们来执行业务代码,加锁完了以后呢,我们来给它unlock业务代码执行完给它解锁,而同样的我们在这读数据呢,还是来加读写锁,当我们写数据是拿到写锁给它加锁,而读数据呢,我们就拿到读锁给它加锁,读写锁还是同意把读写锁好,把这个读写锁拿来,然后呢,我们在这儿要读数据,为了能读到最新的数据,我们在这儿呢,就给他拿一个读锁好,我们把这个读锁拿到,这个读锁拿到以后呢,我们来给它加锁,只要加锁成功,我们就来执行业务代码,好点一个lock,这是我们来进行加锁,当这个加锁呢,应该放在外边,那么加锁成功了,来执行业务代码。
07:30
执行完了以后呢,我们还是翻到了,我来给他释放锁。注意,我们这个加的也是独锁,我们释放的呢,也是读锁,点一个onlock,我们这是一个readlock,好我们在这写一下,这叫加读锁,加读锁那么就来启动一个我们最简单的这个业务,我们把它启动起来,那们现在使用了一个读写锁来控制了我们整个数据的读写过程,我们来看有了读写锁有什么不一样,比如我们先来测试一个最简单的来hello,我们现在呢,先来读取一个数据,好我们就叫read。
08:08
我们来读取一个数据,这个数据呢,默认是存在red里边的,我们存的P呢叫right value,好,那假设呢,给red里边我们先来放一个right value,那们这个right value我们值呢,就叫111,我们来点一个save保存好red里边呢,确认有一个right value,如果我们一直来读这个数据,我来刷新,我们来调用read方法,好回车我发现呢,这个数据啊,刷新刷新我们一直能读到,但如果我们来改这个数据,好,我们来调用这个RA方法,相当于把red里边的这个数据更新,但是呢,我们给write方法加了一个写索,那写索呢,只要没更新完成,期间我们想要读,大家来看,我来刷新。我们发现我们就在这儿等待,等待什么时候我们才能读到数据呢?来把这两个监控一下,来看这个写什么时候写完成了,把所释放了,我们这个数据呢,就能读的出来了,来稍等一下。
09:02
包括呢,我们这个写锁在red里边咋加的,们可以来看一下读写锁就是这个,我们这个读写锁,我们当前呢是写值,我如果我们这个只写成功了,我们来稍等好,我们这个写值一成功,我们这个读值就出来了,读的值呢也是最新的值。只要我们这个写值一更改,我们这个读值,我们在想要读就得等待,所以我们能看到我们这一块的整个过程,那读写所呢,它记录了当前状态,现在是写状态,那想要读取数据,那就必须等写索释放,那写索释放长什么样,我们来稍等一下,我们来看我们这个写索有没有做完我们这个写的任务,好,我们写的任务还没做完。好,现在呢,我们写的任务做完了,我们现在在这读。只要没有写锁的存在,我们一直读,那就跟无锁状态是一模一样的,为了保证我们总能读到最新数据,所以我们加读写锁的好,好处就是我们业务以后呢还会有需求,就是我们保证一定能读到最新数据,因为只要有数据修改,我们就给它加了写锁,只要一加写锁,那你想在我们修改期间,我还没改完再来读数据,你就必须等待了,所以呢,这个修改期间,修改期间。
10:22
我们这个斜锁是一个我们叫排他锁,也就是我们说的这个互斥锁。然后只能存在一个写锁,如果大家都在并发写,那就得排好队,而我们这个毒锁是一个我们称为叫共享锁,就是大家都能用的,你加了毒锁跟没加多锁都一样,因为你加了毒锁是大家共享的,大家都能用。但是现在就会出现我们刚才说的这个问题,只要写锁存在毒就必须等待写索没释放。就必须等待,所以刚才看到我们这个读写效果,这我们来测试了一个读写锁。
我来说两句