00:00
各位同学大家好,我们继续接下来给大家解释一下从写所到读所可重入的读写所的所降级策略和这个关键的考点和知识点。通过前面的讲解和编码的演示,我们已经给大家推荐到了第三步,那么对于上面这一块读写互斥啊,OK了,读读共享肯定OK,那么大家都清楚啊,在这块我们在使用的过程当中,那么读的时候。是可以并发共享,读写的时候是独占,只允许一个写,这个呢我们都在前面呢演示过,那么接下来。更深层次的知识啊,要给大家进行推进,那么就是所见及,你总不可能说读写所啊,就是用一个这么一个API的调用,但是这是不可以的,所以说它的考点所降级,好,那么我们来说说。所降级,它到底是什么?来吧同学们。
01:00
三段第一个理论出处结合我们的官网,那么取自于Java并发编程艺术这本书,它有所降解的说明,来同学们可重入的读写所有所降级的特性。所谓所降级,就是将写入所降级为读所。我们大家都学过Linux。Linux的话呢,我们呢,有点类似于Linux文件的读写权限。就像写的权限要高于读的权限一样,那么所的严苛程度变强叫升级,所的严苛程度下降就叫降级。那这是什么意思呢?那么大家呢,都清楚啊,我们在学Linux的时候,大家应该学过一个最经典的命令。LS。杠L对吧,然后查看了以后,下面会打出什么RWX读写执行这样的权限,那么大家呢。都清楚一般啊。
02:00
写权限高于读权限。对吧,比如说我们所学过增删改查,那么假设insert或者说是。Delete,这是一个写操作,那么select是一个什么操作,假设你去到公司了,你们公司的DBA和Oracle的专家或者MYQ的权限的这么这么一个,他呢,一般。都会清楚的告诉你,你肯定具备select查看的权限,但是不见得你有delete的权限,否则的话你把数据库给干掉怎么办,对吧?所以说写的权限一般要高于读的权限,你只要有写的权限,一般会有读的权限,但是反过来你有读的权限,不一定会有写的权限。好,那么接下来回到这儿。所谓的邪所降级为毒所,就称之为所降级的现象,这句话好说,那么它的要求呢?首先第一个。了解一下,可重入读写锁,它是公平性选择也是可以的。
03:02
默认是非公平。那么就看你选吞吐量还是优先,或者说是排序或者怎么样一个要求,那么。按照我们传递的出和force来决定的公平性选择,第二个re en就代表是什么可重若,那么大家请看这个所也支持可重若。以读写线程为例,读线程获得读索之后能够再次获取读索,而写线程在获取写索之后能够再次获取写索,同时也可以获取读锁,注意。读。读。OK。写。写,但是写的过程当中还可以。获得毒所,这个就叫所见结。所以说。对于他而言,所谓的锁降级就是遵循获取邪索。再获得读索,再释放邪索的次序,邪索能够降级为毒索,这个就俗称读写索的锁降级策略。那么写索的降级降级降级降成什么?降级成为了读索,也即如果同一个线程注意几个同一个线程持有了邪索,在没有释放邪索的情况下,它还可以继续获得毒索,这个就是邪索的降级,降级成为了毒索。
04:23
这句话非常重要,那么再来看这啊写线程在获得写索之后,能够再次获得写索,同时也可以获取读索,相当于这个就是一个什么锁的重入,好第二个按照规则惯例,我们的写法按照官网一样,先获取写索,然后再获读索,然后再释放写索的次序。那么。它为什么要有这个设计好,如果释放了写索,那么就完全转换。为什么独所。这个就叫写锁的降级策略,那么为什么要有这个呢?要有这个特性,它有什么好处啊?提前说一下,为了保证数据的一致性,那么它的设计思想我们回头会拿Oracle公司它的源码来给大家进行总结。好,那么话不多说,弟兄们先了解一下,那么接下来理论完了,来读蝎索降级演示,下面代码说话。
05:22
第一个。重点。邪锁可以降级,但是不可以升级,也就是说邪锁到独锁没问级,但是独锁你反过来要变成邪锁不可以来,兄弟们,这个不是我说的啊。首先,所降级的策略遵循邪索到独索,然后再释放邪索的次序,也即邪索能够降级为独索。如果一个线程占有了写索,比方说right lock.lock它在没有释放写锁的情况下。在这个中间,它还能占有毒所,然后斜索降级为毒索。
06:00
解锁转化成读所。上面这句话和这张图就是我们。写所降级的流程和策略写。示范这个中间可以获得读索啊,写到读好来JAVA8的官网说明所见及策略,所以说你绝对不用担心这个理论的出错,官网要求的巴拉巴拉这一段。很好翻译一下。读写锁它本身就是个重入锁,还允许通过获取写入锁定,然后读取锁,那是不是获得写入锁定,然后再读取锁,然后再释放写锁,从写索。到。读取所however,但是你要想锁升级。相当于说升级从一个读索到写锁的话,这是is not possible是不允许的。OK,那么来,同学们。所降级就是为了让当前线程感知到了数据的变化,目的是保证可见性。那么读到这儿,你可能会觉得这个理论让你有点懵逼,这个为什么我们会在这儿讲?OK,是Oracle官方的例子。那么接下来,那么弟兄们,我们呢,来吧。
07:16
直接呢代码说话,我们呢,先给大家演示啊,再来说我们的结论走。这是我们之前讲的缓存的这个读写所API级别的会用了,重点不是他重点就不考你这两句话。读写锁的所见及策略。首先所降级获取邪索,再获取读锁,再降级为。在示范写所的这么一个次序。解,索降为毒索,也即如果一个线程占有了斜索,在没有释放斜索的情况下,它还能够占有毒索。读没有完成的时候,写所无法获得所,必须要等着读所完成以后才有机会写好,那么同学们,理论知识我相信你听的有点烦躁了。接下来。
08:07
代码说话一看就懂,再结合前面的理论,你会发现没有一句废话,来吧,兄弟们。正常情况下啊,那么咱们说。假设啊。AB2个线程。你一般是这么干的啊,假设现在这个县城啊,那么。是我们的。哎,这个线程他来负责先写数据,Write look第look那么O了。写入没问题吧。那么假设right look点。安洛克他是不是写完了,那么这个时候你这个B线程没问题吧,那么A线程写完了,我B线程来读啊。也加入一把锁。好了,那么这个时候呢,这个就是我们的读取这个答案都清楚啊。隔到这儿啊,洛克假设AB2个线程A写完了。
09:05
B来读,这个是最简单最经典的,那么大家呢,都清楚,OK,那么先写完,再读取几个线程,两个,比如说把它们两个对调。也可以,那么这次啊,假设啊。变成是这样。这是我们以前的,那么就是假设A先来读取,B再去写入,先读再写,只要是两个线程,一般我们都这么做,我相信大家没有任何问题,好,接下来啊,思维方式变一下,那么。本列。假设。Only one一个。同一个线程,听懂这意思了吧?那么来,弟兄们。请看一眼。按照我们的规矩。这个时候是邪索。写若没问题吧,那么正常情况下写完是不是叫我们的这个write look unlo现在只有一个线程啊。
10:06
那么听好。假设这个线程啊。在这儿做我的各种业务逻辑。没问题吧,同一个线程做完以后。此时,还是他。他可以马上写完了以后,假设这个业务逻辑,这是最后一行了,假设41行,最后一行。他自己。在写完以后,他马上想读到自己的结果。防止别人来修改,马上可以同一个线程获得读所。OK,来,同学们。完了以后。写完了再去读读,这块又是另外一段。Business等等等等,OK,那么相当于说我写完以后,我马上去读,此时同学们请看这个效果。
11:00
写说来。好,那么在这啊。我们再给他细化一下。这儿有个。读取。给大家看。那么现在。Lawyer。斜在这儿啊,这是按洛克大家看。鞋。读,是不是锁的降级,同一个线程同一把锁从解锁降级为毒锁来?是否符合我们的流程,获得协索,这个时候是不是获得协索,然后在获得协索和示范写索之间,这是获得协索,这是示范邪索之间,我可以获得一个独索。OK,然后在这块写完了,我们也读完了,OK,相当于说上面写完了,马上就去读。那么这个时候就防止别人来修改我的数据,我可以读到我修改完以后的最新的,那么这个也就是俗称写后立刻读。
12:00
俗称同一个线程的写后读。OK,好,那么这种情况下。就是我们的是吧,写所转换成读所,俗称为所降级,那么下面同学们过来。换一下。现在。解锁。毒所。降级没问题那。我跟你对着干。我非要是毒所。这个是毒吧,这是最后毒所示范,但是毒所里面可不可以这么干呢?怎么来,同学们,我们呢?反过来对调。同学们请看,现在读锁能升级为写锁吗?不可以在这着你没有读完,也就是说没有到unlo read德读所的read lock.unlo这一行没有完成之前,我这卡着呢,那么所以说得到我们的第二句话,读没有。
13:02
完成的时候。写所无法获得所,必须要等着读所读完以后才有机会写,因为你正在读取呢,我又去改你的数据,那么这个是不是有点类似于是吧,你读的数据就是三的呀,哎,我这读这这一秒钟我读的这个数字是五,下一秒钟你把它改成88呢,那么这个时候到底是五为准还是88为准?所以说这个时候同学们就可以看得出,你想从读所升级为写锁不可以,必须全部读完以后我才能写,有点类似于我有s selectck的权限。我想马上获得delete的权限很难,但是我可以,只要我能够有写的权限,这样一下成为读的权限没问题。所以说同学们,搁到这儿,我们可以得到这个结论。如果有线程在读,那么写线程是无法获取写锁的,这是一种背光索的策略。OK,那么可以这样级是绝对不可以升级的,还在这儿,你看读取。
14:05
毒所没有释放的时候,邪锁根本插不进去,所以说所降级就是两句话写。读师范写作。但是读。没有完成的时候解锁无法获得,OK,这个就是我们的所见局的知识点,那么接下来我们来看一下,我们是不可以所升级的。刚才可以看得出一门原档,However,升级服用一个读索去写锁的话,Is not possible在这儿想升级一个毒索再到邪锁的话。撞上钢板了吧,Is not possible所以说,读索获得读所想获得写锁。毒所,再获得邪所在示范毒所,那么弟兄们,不好意思啊,那甭管你是这么干,邪在哪儿?那么来吧。我们不管你这一行读所在哪,也就是说你想从读所变成写索,不管你这个示范是在这还是在这儿,没有任何意义,哎,一句话,读到写不可以。所以说同学们这个时候。
15:09
Error也记在我们这个过程当中。当读索释放。使用抢占使用完成释放了以候,那么这个时候它才可以获得写索,OK,一句话,读索被使用的时候,如果有现程尝试获得斜索,该写索线程会被阻塞,刚才已经演示了,所以需要先释放所有的毒索才可以获得斜索,那么弟兄们请看你这个毒索,只要。没有安洛克的时候,其他的写索拿不到,那么所以说弟兄们,我们改吧改吧。读读完了以后再来写,那么来来试一下我们的效果。毒所。完了马上可以获得写索,所以说严格按照我们的文档上面按照官网的要求,Is not possible,这是错误的,下面这个才是OK的,好,所以说弟兄们。
16:03
这个就是我们的是吗?所的降级从邪所到读所是可以的,好,但是读所没有读完,写所想获得是不可以。OK,好,那么读写锁它是互斥的,那么来,同学们,通过刚才我们来简简单单的搂一眼。邪锁和毒索是互斥啊啊,因为拍黄瓜切黄瓜,你选哪一个啊?这当然,它这的互斥是线程间的互斥啊,比如说A在写的时候B不要来读,B在读的时候A不要来写好,那么这个呢,它为什么要有这些特性啊,那么主要是读写所要保持写操作的什么可见性,至于说这个,我们待会儿会说详细的给大家分析,你先记着,就是我写完以后写后读,我想马上读到。因为如果允许读索在被读取的情况下对写索的获取,那么正在运行的其他读线程无法感受到当前写线程的操作,拿不到最新数据。因此啊,我们分析读写组的时候就会发现它有个潜在的问题。
17:04
读所结束,你要读所彻底完了以候写索,才有望获得写所独占的时候就是写的时候读写全部读的OK。小口诀就这么一句话。也即,如果有现成正在读取。写线程需要等待读线程释放以后才能获取写索,至于说为什么我们后面见为什么,就是一句话,保持写操作的可行性。那么。读写锁,读的过程当中不允许写,只有等待线程都释放了,读索当前线程才能获得解锁,也就是说写入必须等带,它是一种悲观的读所。人家还在读着呢,你先别进去写,省得数据乱。我还在卫生间里面呢,你不能先进去把我拖出来对吧?后面的话就不说了,OK,省得组局乱好,那么所以说兄弟们。那么从这我们可以看得出它的效果是什么?
18:02
人家还在读着呢,你先别去写。OK,那么这个时候来。人家还在读着呢,你先别去写,如果读的线程特别多,你写的线程也拿不到,是不是容易导致所饥饿?那么下面我们有没有一种牛逼的方法?读的时候也能进去呢,这个就是我们lock它。第四部出现了意义。啊。我们后面会详细讲啊,这儿先开个头。读的过程当中也允许获取写索介入,这个特性相当牛逼,注意读和写两个操作也让你共享,当然它不是真的共享。这样会导致我们读的数据有可能是不一致的,所以需要额外的方法来判断读的过程当中是否有写入。这是一种什么乐观的有所思想?虽然乐观所的并发效率很高。但是。但一旦有小概率的写入,导致读错的数据不一致,我们需要能够检测出来再重新读一遍。说穿了,为什么step lock比读写索的性能更高,就是读的时候我很乐观,我认为我在读的时候不会有人改。
19:13
那么这样的话呢。他当然允许你在读的时候也允许写所介入性能自然度高,可是问题是很乐观啊,那悲剧啊,确实有人改了呢,那本次读取作废,我再读一次,哎,所以说它是有这么一种思想,但详细的我们后面会展开,那么这儿我们就给大家解释了,什么叫所降级。
我来说两句