00:00
各位同学大家好,接下来我们为大家介绍happens before先行发生原则的。偏学术范,官网上要求的。八条,那这个呢,比较晦涩,比较难懂啊,可能你学完第一遍以后稍微有点懵逼,那同学们没关系,多听两遍,老师也会耐心细致的给大家讲解清楚,嗯,还是在这个当前内卷的要求下面多做点难的,OK,因为做难事必有所得,对吧?我们希望大家呢,功力和内功上更进一步的提升,好好理解高并发多线程是如何控制的。来吧,哪八条呢?分别是。自序锁定V传递线程的启动、中断、终止、终结。来吧,同学们,我们。一步一步的走,一块一块的敲,那么就会明白为什么我们写这些程序啊,好像只需要简单的加个锁,Lock and lock snch就可以控制线程。哎,其实底层。
01:01
结合我们的GM规范,结合我们的before,那么语言级别、编译器操作系统级别是给我们做了很多规定的,所以说我们有必要了解它的底层运行原理来。首先说次序就是。先来后到,说白了,那么大家还记不记得我们之前讲过这个XY案例?假设两个特性默认值都是XY默认值都是零,对吧?到底这个Y是等于零还是等于五,我们前面说过,是不是就要有一个包含可见性和有序性的约束,第一个改了,让我知道后面的要明白前面的X被改了,第二个前后顺序到底是X还是Y,那么这个就要靠次序规则来进行满足来。同学们。他保证一个线程内按照代码的顺序写在前面的操作先行发生于写在后面的操作,哎,所以说前面那个X等于五,如果已经是写在前面的操作,那么一定要保证后面的Y能够感知啊,那么加深说明的意思就是说。
02:09
前一个操作的执行的结果可以被后续的操作获取,我能看到你的劳动成果,OK,然后作为参数续传给后面,保证程序井井有条,步步为营。讲直白一点就是前面一个操作把变量X啊复制为一了,那后面一个操作肯定知道前面的X啊已经变成了一,我可以续用好,这是第一个次序,第二个锁定。啥意思呢?一个按look操作先行发生于后面,这个后面主要是指时间,时间上的这个先后啊啊只是一个时间上的提示,那么过可以把它理解为一个按lock操作先行发生于后面,对同一个锁的什么lock操作,那么直白的说一句大家都清楚啊,我们假设。干了这么一个object,那么假设啊。现在对于同一把锁object这个同步代码块里面,线程A1定要先按lo同一把锁。
03:08
之后B才能获得该锁,A先行发生于B,假设现在来了一个A,它是不是一定要先进入它先获得锁,用完了以后,释放这个锁以后。B才能够获得,没问题吧。再说直白点,就说同学们。我们一定写过这个代码。对吧?假设对同一把锁洛克,然后呢,这是安洛克,那么一定是先洛克才能有安洛克,对吧,然后呢。假设。后面这个lock又要进行锁定,那么一定要等着上一个按洛示放了第一个次序的原则一定要先按落了以后我。知悉并看到,然后对于同一把锁我才能够获取,OK,所以说呢,这个就是我们的什么按lock操作,先行发生于后面对同一个所得lock操作,一句话,你上面按lock了,我下面是不是才能lock,对吧?这个所的获取的先后顺序,程序执行的先后顺序,咱们得说清楚了,这个就叫什么第二条锁定规则,第三一个的什么变量规则,以及。
04:19
对一个维特变量的写操作。先行发生于后面,对这个变量的什么独操作。前面的写对后面的读是可见的,这里的后面同样是指时间上的先后啊,也就是说假设啊有一个变量是被VE的关键字啊所修饰,那么它写对后面的读是可见的。哎,这个VE tell呢,同学们呢,也不用担心,后面我们会有vela这一个关键字啊专门的详细讲解啊,涉及到底层汇编,内存屏障相关的讲解,但是在这我们就大家记着,只要一个变量被V修饰了,马上。会发生什么?对一个Y变量的写,只要你写了,先行发生于后面,对这个变量的读,大家都可以什么即刻收到这个消息,可见性获得保证。
05:07
第四个传递这个简单。如果A。先于BB又先于C,肯定可以得出传递依赖嘛,A先于C,先有你的爷爷,再有爸爸,再有儿子,那么肯定可以得出。爷爷先行。发生于。儿子当然到他这边已经是孙子了,对吧?那先有爷爷才有孙子。好了,这是我们的第四条,那么接下来我们来看一下现成的什么启动规则。大。那说人话,我们大家看啊,我们干脆。先来写一个。这个呢,我相信大家。已经是非常熟悉了。OK,那么现在呢,我们就写这么一个简单的,先写好,咱们来看啊,什么叫start哪,就是这个。
06:01
什么意思呢?线程对象的start方法优先发生于子线程的每一个动作。换句话说,就说虽然说第19行在第20 start在第20行,那么好,我们直白的再说一点啊,假设改造这是T1,那么t1.start。就是说一你要想执行19行这个线程里面的这个内容,一定是22行t start之后线程的状态变了。从旧绪对吧,从新建你有一个线程到reable就绪的状态,这块才有可能执行START1定要先执行完且生效了以后,线程里面的业务逻辑才能继续执行,OK,所以说线程对象的start方法先行发生于此线程的每一个动作,这么说能跟上先start之后里面的。内容才能执行好。这是我们的第五条,第六个。线程中段规则interrupt能理解为什么要先说说interrupt了吧?现在我相信大家再跟你说中断标识位,你应该不陌生了这个知识来,同学们,它的意思是这样的,对线程因特绕的方法的调用。
07:12
先行发生于被中断线程的代码检测到中断事件的发生,这块有点难懂,说人话。第一个。我们可以通过interrupted检测是发生中断,我们是不是那个布尔值啊,前面这个都说过,把这两个翻译,也就是说你要先调用interrupt这个方法,设置过中断标志外,我才能检测到中断发发生过一句话,同学们记一点,Interrupt你要设置过了以后,我后面是不是才能检测到,诶这个标志位从默认的从来没有过中断,从默认的副变成了true,哎,它是这个意思,所以说对于interrupt方法的调用。先行发生于被中断代码的。被中断的代码检测到中断事件的发生,就是你要有这个结果,我是不是先调用过这个方法,好比说现在。
08:03
我一定是先发烧了,身体不舒服,感冒先生病了,你温度计量了以后才明白,我干到了39度,对吧?是这个意思,好,那么这是我们的第六条。中断,那么第七条注意中止和终结啊,这个两个英语单词都不一样。Termination,它的意思是这样的。线程中的所有操作都优先发生于对此线程的终止检测。好,我们可以通过一。Alive等手段检测线程是否已经终止执行。他的意思是这样的,我们一个线程啊,比如说这个T。现在start以后它就运行,那么假设啊,在这个里面我停。30秒钟,那么相当于说这个线程是不是迟迟没有结束,那他的意思就是说,我现要检检测一下这个T线程活不活着,前提是线程中的所有操作都优先发生于子对子线程的什么终止检测就说。
09:02
你要来决定这个线程已经死了。他死之前一定会,正常情况下会干完自己的所有事情了,以后OK,他才会彻底生命周期终结,忙完全部业务逻辑之后,先行发生于对吧,我们的最终。结束状态,那么结束以后is alive,那么假设这个现场活没活着就返回给你出和force死有点类似于什么生死,生死先生下来才会死,OK,这个顺序是有一个逻辑不能检测,这是它好第八一个对象的终结规则,Finalize,那么它什么意思呢?来。一个对象的初始化完成构造方法执行结束,先行发生于它的finalize方法的开始啊,我相信读到这儿同学们是绝对懵逼的。那么说人话的意思就是说你。那么首先啊,这个final知不知道什么意思啊,就是Java g vm里面就是Java虚拟机,一个对象要被回收的时候,它会最终来执行一下,这个方法有点类似于死后遗言,哎,它的意思就是说一个对象初始化完成构造函数,执行结束就是尿。
10:09
一个对象先要六出来一个对象才可能什么垃圾回收。收回去一个对象听懂,所以说呢,在这儿我们来看一下这个东东啊,Finalize,那么在这儿。Finalize啊,注意我这个是JAVA11的API,那么和八也差不多,这个时候请看啊,它的意思是这样的。这有句关键的话。通常目的是在对象被不可撤销的丢弃之前,注意不可撤销的丢弃是不是当将垃圾了,就是垃圾回收之前执行一下什么清理操作,那么如果你在这个方法里面写了一些话,或者写了了业务逻辑,就是相当于说你在收灭了这个对象,收集这个垃圾对象之前最后的遗言,但是有这个遗言的前提是不是你要先构造函数,先执行完,我这个对象曾经被你溜出来过,确确实实,垃圾回收的前提是这个对象没有引用指向它,它先从一个有用的对象变成一个垃圾,才有你的回收。那么一句话,它先要构造函数,先成成生成一个对象,才会有被你当成垃圾回收的可能,对吧?所以说这个物品一定是什么从新到旧,你买回来用过以后才会变成垃圾,所以说它的意思就是说对象没有完成初始化之前,就是没有构造之前,还没有尿出来的对象,这个对象都还没生出来呢,怎么可能去死呢?生已经生死生死没有听说过死生死生嘛,对吧,是不能调用反纳方法,因为反。
11:31
赖这个方法它基本上就是垃圾对象,你看不可撤销的丢弃之前执行一点什么清理操作OK好,那么所以说这个呢,就是我们的什么对象终结规则,好,那么同学们这个就是我们happen before的是吗?八条原则,次序锁定、传递、启动、中断、终止、终结。
我来说两句