00:00
各位同学大家好,接下来为大家介绍多线程先行发生原则happens before,那什么叫先行发生原则呢?一句话就是决定多线程之间要配合,谁先谁后了以后互相让其他线程获得感知,那么这个要遵守happen before,多线程之间的协作才能满足。可见。OK,但是呢,这张知识呢,比较可以这么说吧,是整张里面最晦涩难懂最啰嗦的理论知识。我当初自己了解的时候觉得有点头大,那么同学们第一次听可能会有点懵逼,没有关系,你能听懂多少是多少,那么他总共有八条原则,我会挨个逐步的细化的给大家说清楚。那么面试过程当中,如果能八条你能全部说出来,这个最好,如果不行,那么放心,老师也给大家准备好了话术,就按照我们准备的精简版向面试官陈述即可。好,那么同学们来吧,那么这个是是什么?在GM规范当中,如果一个操作。
01:00
执行的结果注意是什么?执行的结果需要对另外一个操作可见或者代码重排序。那么这两个操作之间就必须要满足happens before先行发生原则、逻辑上的先后关系以及相应的要求。什么意思呢?前面我们说过GMM的内存访问。那么两个两个或者多个多线程只能对同一份主内存的共享变量进行拷贝到自己本机以后,本地以后修改再写回去。那么一写回去就告诉。大家的结果就是说这个结果已经被我改为最新的了,我希望大家能够立刻看到,那么这个时候我们先后上逻辑关系,是不是一定会有我A线程先改完了,然后再写回主内存里面通知大家,这个叫可见第二个代码重排序,就是要在不影响结果的前提下,你才通过什么指令优化,内存优化等等来给我的顺序打乱去执行,但是一定要保证结果。一致,所以说这个逻辑上是有先后关系的要求的。那么接下来。
02:01
仅凭这么一句话,我相信大家或多或少还是有点不熟悉。那么按例说话来,同学们。下面请看,把下面的笔记我先遮挡一下啊。X等于五,线程A来执行,Y等于X,线程B来执行,那么上述就称为写后读一句话,线程A先给一个变量X等于五,线程B再去读取X等于五这个变量,再赋值给Y,那么我们的问题是。按照你的理解?Y是否100%一定绝对等于五呢?答案是不一定,为什么。第一个。如果线程A的操作X等于五。Happens before先行发射线程BY等于X,也就是说符合这个前后规范,那么可以确定线程B执行后Y等于一定成立,这个就是我们要说好这个规矩,因为多线程有可能A读到这儿,突然上下文切换,A就在这挂起了,它赋值还没赋完呢。
03:06
那这个时候我B马上过来去读X等于多少,这个时候可能X的默认值就是个零,此时它就会把X等于零赋值给Y这个值啊。他不一定每次都是一样的,那这个就麻烦了,我们这个程序每次运行的结果对不对,就变成了什么,看心情就变成什么开盲盒。有可能正确,有可能错,那你就疯了,或者135正确,246错误,星期天随机,那这个时候,所以说我们要定好规矩,因为你执行的顺序不一样,绝对导致我们的变量的值是不一样,所以说如果我们有定下一种规矩,我们想达到的效果。一定是A先执行完了,B在执行,那么这个时候Y等于五是成立的,如果不存在happens before这种原则,Y等于五就不成立,所以说这就是happens皮的原则的微列,那么结合我们memory,它也是具体的一种体现,大家要守规矩。保证可见性和有序性的约束,那么这个时候我们的答案才是一致的。来,那么先行发生的原则说明的意思是这样的。
04:08
日常工作中有没有发现除了我们加什么size对吧这样的关键字以外,正常情况下,即便在高并发的前提下,我们也好像也很少主动的去加一些晦涩难懂的是吗?啊,Synchized来完成。因为啊,你这些要是全部人工手工去加的话,那么很多操作都会变得非常啰嗦,而且加大了程序员的负担,甚至还容易写错,但是我们在Java写并发代码的时候,好像也没有说每次要去Java和。Snchize的,也就是说我们没有时时处处字次的添加这些关键字啊,这些复杂的关键词来完成程序,因为这是Java语言当中GM的原则下有一个先行发生的原则,一出娘胎的时候就给你做了这个限制和规矩,大家只能这么干,OK,那么这个时候来这个原则呢,是非常重要的啊。
05:05
它是判断数据是否存在竞争,因为谁先谁后了以后,就大家一贯而行,顺序而入,即便有高频发,我们可以锁来控制,对吧,一改完以后给大家通知啊,有可见,那么这个时候顺序确定了以后,座次排好了以后,那么对于现场的是否安全就非常重要,依赖这个原则,我们可以通过几条简单的规则,一揽子解决病房环境下的两个操作之间是否可能存在冲突的相关问题。而不需要陷入加热内存模型苦涩难懂的底层编译原理之中。你也不要去说那么多了。高级语言已经出娘胎,给你设计好,我就遵守这个规范好,那么所以说我们先来看啊,这就是我刚才所说的,一要求大家必须掌握总原则。但是学习我们全部按照官网去讲,有八条,那么来happens before,假设你面试回答就回答这个就行了,一句话。来吧。
06:01
现在。如果一个操作先行发生于另外一个操作,那么第一个操作的执行结果将对第二个操作可见OK,而且第一个操作的执行顺序排在第二个操作是吗之前,也就是说A执行完了。有这个结果才能去执行B,且B能看到上一个执行的结果给我传递下来,OK,解决了先后问题,第二个,两个操作之间存在着happens before的关系,并不意味着一定要按照happens before原则之间的顺序来执行。如果重排序之后执行的结果。与happens before关系来执行的结果是吧,一致啊,就是只要最终结果一样的前提下,那么这种重排序并不非法,也就是说它可以去重排,OK,那么一个是顺序,一个是重排,那么来吧。最经典。现在我们来看。以值日为例,我希望周一张三指周二李四啊,假如有事情调换班可不可以,完全可以,那么现在我们是不是可以这么干?第一个周一是张三。
07:09
第一个执行操作的执行结果相对第二个操作可见,周一张三值日把教室打扫干净了,第二天周四来看,第二天李四来看,只要教室干净的,那么张三的结果是不是对,我可见我就知道张三搞定这个叫可见,OK,那么这是第一个,第二个。什么叫重盘?就是按照,并不意味着一定要按照原则制定的顺序来。我们。之前商量好的值日排班,周一张三,周二李四啊,没关系,如果没事儿,大家就按照这个执行,但是突然不好意思啊,张三临时有事,或者李四临时有事,他们两个。干嘛要跟后面的同学换班?那么这个时候假设啊,现在张三和李四去换班了,没关系,我只关心最终的结果,就是说只要今天有人直热就行,原则上我们制定的顺序,周一张三,周二李四,但是假设今天周一张三执行不了,你们两个按照编译器优化,为了取得同样的效果,甚至更好的效果。
08:11
李四啊,你来填张三的缺张三你们两个对调,只要有人直着就行了,没关系,但是注意。结果一致的前提下,你可以不遵守原来的顺序,但是如果结果不一致啊,那不好意思啊。这个时候假设张三要跟李四调班,那对不起,那李四也说我有事,那这个就不OK了,所以说这个班调不成,那么我们的重排就要被禁止,OK,所以说一个叫可见,一个叫重排,那么123。这个相加也跟前面的已经说过,第一个操作和第二个操作它们俩是相等的,重排并不违法,一句话。并不一定要按照happen的原则来制定的顺序来执行,一二加二加三,怎么着,结果一致吧,等于三加二加,所以说它们两个是一致的,OK,那么这个就是我们happen before的总原则,主要就是什么顺序和可见OK来,这个就是我们对happen before做一个最总的原则的简单陈述,接下来就是这八条。
我来说两句