00:00
不可能。即便是像阿里、淘宝、美团,像他们这样的一个并发量出现的可能性都极小。但是没办法,人家面试会问。好了。呃,讲到现在为止,我觉得这道题我就讲清楚了啊。呃,标题值50万,如果你面过了这这道题,你要是拿出这道题来,面试官你噼里啪啦,你给他说清楚了。基本面试官不太会问你底层的问题了,就嗯。嗯。好。好的,看这里。好,我们继续,那现在问题又来了,那这个volatile起了什么作用呢?为什么加了它就能解决呢?认真听我讲。
01:00
呃,Vola起了这么一个作用,用volatile修饰的任何内存空间。在它上面执行的这些指令。不可以乱续。我再说一遍,叫做禁止乱序,用V修饰的这块内存空间,就是扭出来这个对象,这个对象扭出来的在它上面执行的一些指令。比如说要读,要写好,不可以乱序执行。既然不可以乱续,就绝对会防止住其他的县城拿到这种半初始化对象了,你必须得初始化完了之后才建立关联。OK。现在的问题又来了,他是怎么阻止乱序执行的呢?这就是下面我们要讲的问题,叫内存屏障。今天内容已经挺多了,大家还能跟上吗?能跟上的给老师扣一。
02:04
嗯。嗯。内存屏障呢?我们就聊比较简单的概念吧。其实。物质就在这画啊。好,再看这里。呃,我们下面来聊,就是加了AVO之后,它是怎么阻止。那这个指令的乱序执行的怎么阻止的呢?其实阻止一个指令的乱序执行。也就相当于这有一条指令。
03:00
呃,这有一条指令,两条指令,我不允许他换顺序,那我怎么办呀,中间给它加一个障碍物就行了。两条指令之间加一条内存屏障。这是内存屏障的概念。我去。稍等片刻啊,这个椅子出了点问题哟。嗯。没事没事,是我的椅子出了点问题啊。啊,我这个椅子差点把我给。是过去。椅子没锁住啊,没事没事,嗯。嗯,老师吓人,老师又不是。老师又不是大姑娘,生娃娃想什么人?
04:03
好,看这里啊,呃,我们来聊这个内存屏障这件事。呃,也就是说在两条指令之间啊,我们加一个内存屏障就可以了,大家好好听啊,这个内存屏障呢,有各种各样的屏障。我下面跟大家聊呢,在。JVM这个级别的凭证。是什么意思?JVM级别的屏障呢?注意GVM是个什么东东啊,JVM是一个规范规范规规规规规规范,它并不是一个具体的实现,所以它要求的这个内存屏障。好好听我讲,这东西并不是具体的操作系统级别或者是硬件级别的实现,我再说一遍,由于JVM只是一个规范。这个规范要求volatile修饰的东西得给我实现内存屏障,但是硬件级别或者我的host级别,或者我操系统级别,它到底是怎么实现的,实际上跟JVM的规定并没有直接的关系。
05:09
这块大家听懂了吗?来,能跟着老给老师扣一。我们先说JVM级别的实现,网上有很多关于讲内存屏障的内容,很多很多,他讲不清楚的一个主要的原因就是因为他们混着讲。他们会把。在JVM级别的内存屏障。和硬件级别、内存屏障完全混在一起讲,这俩不是一个概念。GVM级别内存屏障只是一个规范的要求而已。GVM级别的屏障。再看这里。呃,GM级别的屏障呢,大概有呃四种,这四种呢,我花30秒给你讲清楚,虽然你看到过,但是你不一定能理解的了。呃,这四种我画三种给你讲清楚。这四种屏障分别是low load store store store和store。
06:05
听我说,漏是读,Store是写。Load load的屏障是对一块内存,上面是一个读,下面是一个读好中间这个屏障叫load load,上面这条指令跟下面条条指令不能换顺序,Load load。Store store上面是store,下面是store,不可以换顺序。好了,我觉得我讲到这儿,剩下的应该不用我说。来,能get到的老师扣一。很简单是吧。关于嗯,JVM级别,对于VO修饰的变量,它到底要加什么样的屏障呢?它是这么来加的,这块大家不需要记住,面试也基本上不会面到这种深度。还没遇到过。好。
07:00
看这里。凡是修饰的内存。当你要对这块内存进行修改的时候。在JVM级别要求前面加一个store store后面加一个store,啥意思呢?你这里要要注意啊,你这里头是要对它进行写了,就是store嘛,那前面的store必须先执行完。就是你先写完了。得到最终的结果了,我再往里写。后面等我写完了,你再开始读。保证一致性。如果是读的话呢,上面的全读完了,我读完了,你其他人才能读。我读完了,你其他人才能写。就保证了。线程之间的可见性,你自己分析一下就行,当然听我说这个东西是还是那句话,是JVM层面要求规范要求的一种实现,实际是怎么实现的呢?实际不是这么实现的。啊。
08:00
这块还能跟上那个老师扣一我们继续。嗯。嗯。来。好,再看这里。呃,我讲到这里呢,讲了乱序,讲了忘了禁止乱序,呃,我相信应该有同学呢,开始问这样一些问题,到底什么样的东西允许乱续?为什么刚才先建立关联,再初始化对象,他俩就可以乱序?那什么样的指令不允许乱续?这块大家有这个有这个问题的,给老师扣个一来。嗯。听我说啊,这就是著名的happens。Before原则。
09:02
我估计如果你们稍微读一点技术文章,都应该接触过这个词,这个词呢,叫happens before。Happens before的意思呢,就是什么什么要求在什么什么发生之前,你比如说你这个线程的销毁一定要是在呃,线程的创建之后,你不能说线程还没创建,你先把它给销毁了,这肯定不行。有依赖关系的肯定不允许。大家听我说,在JVM层级规定了八种happens before原则。除了这八种之外的随便重排序,这八种里面并不包括先建立关联才能初始化。而这八种呢,不需要你背过,别这样背,没意思。这八种也没人问,都是非常简单的一些个概念。总而言之,言而总之。在语言规定之外的任何的其他语句可以重排。
10:00
这就是哈皮原则,当然我讲到这儿呢,我就顺带着给大家讲另外一个概念吧,因为我怕你们有些同学读到。一个呃,一些一些一些文章的时候啊,这个听不懂,听不懂。看不懂,大家读文章有没有看到过这个词,这个词叫as。If。Cereal。来看到过这词的老师扣个一,我认识一下。嗯。应该是看到过啊,这个词呢,叫as if zero,呃,翻译成中文的话呢,叫看上去是序列化执行的,这句话的意思呢,其实本身指的就是CPU的乱序执行,CPU呢,你给他两条指令,很有可能第二条指令跑到前面去,但是能不能跑到前面去,最终的结果一定是这样子的,不影响最终的结果值,就跟前面似的,你X等于一,Y等于A,这两句话谁先执行,不影响最终的结果值。
11:02
是在单线程里头一颗CPU的时候。所以单线程里头。这两条指令,不管它前后执行的顺序,看上去as if像是一个顺序,执行的就是这个概念。所以as if的概念指的是单线程里头执行最终的结果。不影响,不影响改变,不论你怎么进行程序单形程执行结果不行,改不不进行改变,这个叫做as ifre。OK,同学们,我们可以继续的老师扣个一,下面我们就来聊volatile最底层,最底层到底它是怎么才能实现的这个屏障呢?好,我们稍微。看这里啊,我们稍微回顾一下。嗯,我到现在为止呢,给大家讲了很多的内容了。
12:00
我给大家讲了什么是CPU的缓存,呃,缓存和内存之间到CPU他们怎么是一个级别关系,讲了缓存行,讲了缓存一致性的协议。呃,讲了缓存之间怎么保持一致。我讲了CPU之间的乱序执行的一个概念,向大家进行了证明,给大家讲了DC为什么不能够允许它乱序。给大家讲了VO在JVM层面是如何阻止乱序的,给大家讲了内存平衡的概念。但是。一个GVM的就是hotport的实现,对于volatile,它并不是使用了那些特别精巧的内存屏障,刚才我看有同学问我说老师,硬件级别内存屏障到底怎么实现,听我说很简单,他们有自己的。对应的指令。如果是英特尔的CPU,它本身就支持好几条指令,这条指令叫S,叫做。写屏障store FS嘛,这条指令叫al FS叫load fence叫读屏障,这条指令叫M,就总而言之,在汇编上,它直接就支持内存屏障这件事。比如说当你前面写了一个store指令,中间你加了一个sence,后面又写了一条store指令,那么这两条就不就不可以换。
13:15
就是你写汇编的时候得自己写,这是非常精巧的,效率很高的一个实现,但是听我说,House并不是用这些指令来实现的。核报是怎么实现的呢?大家看这里。嗯。偷个懒。我懒得给大家跟那个那个那个那个C加加的源码了。好,呃,如果你真正的想了解house到底怎么实现的,好,听我讲。实现。由于你加了任何volatile的一个东西,它都要编译成为自解码,叫code。
14:05
而Java的子解码是解释执行的。所以你想了解的话,去这个文件里面去看,这个文件呢,叫code自解码的解释器,点C文件。嗯。由于大家伙并不具备,多数人并不具备自己去编译host能力,所以有的时候我就我我只能是直接直接拿给你看啊,这没招。基础太弱,我也只能是慢慢带喽。就没打开。我就懒得,我不给你打开了,呃,看我们的笔记就行了,笔记里呢,我也给你解释的很清楚。呃,当你找到这个C加加文件的时候,找到这句话。If is。如果这个。是VO修饰的。
15:00
修饰的时候,它实际上调用了另外一个类叫order access order access顺序访问里面的方法。而这个分方法呢,分函数。篱笆吗?具体是怎么实现的呢?具体的实现是这样来实现的。看这里。它仍然是一条lock指令。后面跟的被锁定的那个语句叫ADDL叫ADD。ADD呢,就是添加增加的意思,给某个寄存器,每个寄存器呢,RP加了个零。Lock来实现的。呃,我讲的这块大家还能跟得上吗?能跟上给老师扣个一来。嗯。就是总而言之,言而总之,我们跟这跟了半天,跟来跟去,跟来跟去,实际上最终的一个实现就是这条指令来实现,这条指令叫lock at l。
16:04
昨天啊,我们讲了synchronized,它的最终的一个时间是什么,你们还记得吗?其实最终的实现呢,也是一条lock指令,那条lock指令叫lock and exchange。当然,这是CAS的实现。是吧?然后今天我们讲了VOVO的时间是什么?依然是一条lock指令,这条lock指令叫lock and l。好,听我说lock就是锁总线,就是我这个CPU在执行的时候,我把这个总线锁定,其他CPU完全谁都不能访问。后来叫锁总线,那为什么这条指令能实现?为什么这条指令?这一条指令就能够实现VO的两大作用,线程可见性、禁止重排序。好,听我说。请大家记住我昨天和今天讲的两条指令,一条叫lock compare and exchange,第二条叫lock at l。
17:05
呃,基本上面试官怼到这种深度的时候,除了我昨天没有讲完的内容和今天。讲不到的内容之外,你基本上就可以吊起来揍他了。好。我们来分析一下。艾l lock是个什么东东?其实这个这条指令里面IL没用。好,听我说这条指令起作用的就只有这条lock指令。lock指令呢,它是在多处理器执行的时候,对共共享内存进行独占使用。多处理器,好多个CPU去访问这个内存,我去把总线锁住,其他人不能访问,那我就归我独占用了。它的作用是能够当前处理器对应缓存内容刷新到内存,我这里面有一些改变,我会刷新到内存里面,是不是就保证了可见性了?并且其他对应对应的缓存失效,这个缓存告诉你,你失效了,你得重新去读,我不就保证可见性了吗?所以一条lock指令就已经。
18:07
执行了可见性,另外还提供了有序的指令,无法越过这个内存屏障,左右这条lock指令,只要往这一放,前面不论多少指令,后面不论多少指令,谁都不能互相穿越。所以一条lock能搞定。那有同学可能就会说。大哥。你刚才在那牛逼吹了半天,说英特尔CPU支持什么s fans?啊,LS说JVM层级支持什么load load load store,怎么到最后就一条lock指令搞定了呢?为什么呢?很简单。因为好偷懒。如果house做的比较精细化的话。那么它应该是根据不同的CPU调用不同的汇编指令,但是house偷了这条指令完全可以解决所有的问题。行了,我就不用针对每科CPU来进行优化了。
19:10
锁了总线,其他CPU怎么读?程海波?有人进了厕所,其他人怎么办?告诉我。等着呗,等人出来呀,等着解锁呗。社交效率低吗?嗯。好了。那有同学说,老师后面的al有啥作用?AL啊,是没有任何作用的一条语句。但是由于英特尔的CPU规定,嗯,其实都是CPU都这么规定,一条lock指令后面必须跟一条语句,指的是在执行这条语句的时候所总线。那这个语句呢,又不能没有。然后又不能够。说,呃,这个执行点,这是任任何有有有效的东西,有用的东西,所以他就用一条空语句,这个空语句指的是往一个寄存器里面,往里边的值加了个零,等于没做没做任何操作,这些东西都是占座占位置用的。
20:12
当然有人学汇编啊,汇编的控制令是哪个语句,你们知道吗?对,Lock后面必须给你有语句。对。No。不做任何操作。二、听我讲,为什么洛不能跟这个呢?没什么为什么。王八的屁股规定。Lock后面不能跟LP说不定。为什么索总线就不能穿越了。因为。虽然条条大路通罗马,但是我的CPU访问内存只有这一条路,我把这条路给占住,除了我之外谁也不能走,你告诉我其他CPU怎么穿越?为什么这么简单的问题非要老师来解释呢?
21:01
好。呃,这个实验的话呢,比较复杂,今天不想带大家做了。另外呢,昨天讲的那个所升级的过程也非常复杂,今天不想带大家做了。讲累了,已经快失恋了。嗯,今天就聊到这里吧,好不好,日常推课环节,对给介绍介绍我们课程,嗯。哦。我们先介绍,先回顾一下我们今天讲的内容啊。嗯,我今天呢给大家讲了,你们稍后给我讲,闭上眼睛小就行了,嗯,我今天给大家讲了什么叫做缓存,缓存是什么?介于CPU和内存之间的一系列的缓存。第二个呢,什么叫缓存行,读数据的时候一块一块来读,一块就叫一行,一行的大小是64个字节。什么叫缓存一致性协议?CPU为了保持互相缓存行之间的这种数据的一致性所采用的一种协议。
22:03
什么叫做一些个编程技巧?就是你可以强力的让你的小程序,让你的让让,让你的数据不位于统一好,就能够增强多线程情况下的效率。什么叫做乱序?执行前后两个没有关系的语句或者没有关系的指令?他有可能不是按照前后顺序来执行的,向大家证明了这一点。讲清楚了DC为什么不能乱序?讲清楚了volatile到底是怎么阻止乱序的?Volatile在Java层面,GVM层级规定了一些东西,各种各样的规定,但是没用,因为最终的实现就是lock and l来实现的。好了,这是今天我们讲的内容,来有收获的同学老师扣个一。嗯嗯。里面还有一些东西啊,就是这些个。
23:03
实验啊实验,因为相当复杂,呃,就不大家做了,而且里边充满了各种各样的汇编语句,你不一定能看得懂,主要得打基础啊。嗯。作为我来说呢,这个整个的今天给大家讲的东西呢,也是我们课程中的一小部分。这课程呢,我们是分了两个两块,一个叫P7,一个叫P班啊,但是无所谓,你大概理解就什么意思就行,我们这个课程呢,是。总体上是这么一个系列,有M个知识点,加上三个项目,就是有知识点有项目,项目驱动知识点的学习,项目很重要。非常的重要,比知识点要重要的多,我今天讲的只是知识点的内容,知识点内容呢?是在咱们的JVM课程里。啊,今天给大家讲的是JVM的一部分内容。给大家讲了多线程的一部分内容啊。
24:01
呃,这里面的每一个知识点,你呢,打开来呢,都是一堆的内容,我就不给你一一打开了,如果大家需要的话,找小姐姐要一下我们的课程大纲就可以了。呃,课程呢,有一个很重要的特点,就是它的时长非常的长,我们现在是差不多要到2000个小时了。有同学说这是个什么概念,呃,是这么一个概念,那个。我们。如果是你在别的地儿学过一个课的话啊,像那种半年左右每周上三次课,每次两小时那样的课。他们的课程量差不多是200~300个小时。我们大概是他的七到十倍,是这么一个课程的体量,这个没招啊,有同学可能一直问我说老师你这个课为什么设计的时长时间上这么长,呃,原因是我想给大家讲的深入一些。
25:01
同学们听我讲,嗯,就是我相信啊,很多课你应该都没都没见过。就比如说像这种open open jdk的源码分析。就是Linux内核的源码分析。呃,咋说呢,我觉得给你讲透一点,然后你面试的时候就一定是手到擒来的事情,就像今天我给你讲的,你昨天给你讲的SNCH,其实你只要听完都已经深入到这种源码级别了。你怼面试官随便怼啊,但是你别真怼他。呃,就是我想给你讲的更深入,所以必须时间要长。时间不够长,没戏,听懂了吗?嗯,有同学说老师,那你这个课内容又多,时间又长,那我怎么学,我学的过来吗。来,有这个疑问的给老师扣个一。如果别人那学半年,你这就得学两年。
26:01
听我说啊,这课呢,一个特点是。简单解释一下。一对一的一个定制化学习,注意咱们课是定制化的,是面向效果驱动的,并不是说非得要求你所有的细节全部掌握完,你也别这样学无止境。因为我们每年还在不断的更新课程,你想学完这件事是不存在的,但是呢?呃,对于你来说,你只要达到效果是不是就可以了,所以我们是效果驱动,什么叫效果驱动呢?给你举个例子。就是这课呢,是这样的学,给你举几个例子啊,就是这种一对一的定制化的学习,刚才说了啊,课程时长小成。深度很深,怎么才能达到更好的学习效果呢?学习效果就在于一对一。
27:01
定制化学习给你举个最简单例子,你比如说大学生,你想进大厂,有大学生想进大厂的吗?我相信有啊。我们会给你规划一条路线,学我们课程里面的七加一,加一就搞定了,你只要按着来就搞定。啥都不用你想。把你的自己的这种基础告诉我,就是你自己的基础情况,你自己的诉求,短期诉求,长期诉求,你自己的领悟能力,你自己的简历拿给我。我会告诉你,根据你的诉求来帮你设计一条路线出来,比如大学生想进大厂,七加一加一在我们课程里帮你搞定。比如说你设招生想进大厂,你设招生的话,和和那个大学生还是不一样的。那这时候怎么办?赏金大场六加二帮你搞定。你说我想进头条字节字节腾讯拼多多,比较牛逼的企业怎么办?
28:09
算法帮你搞定,我们算法课是左成云,左老师在别的地儿讲课,差不多六七千块钱的那个课。全程的帮你搞定。比如说我如果是零基础的说,我特别弱小,我想走到一个更高的薪水的岗位上去,从A课程到P课程,一系列课帮你搞定。比如说你说我想全面提升怎么办,说我时间很充裕,我也没有说什么,短期内非得就想跳槽涨薪。没关系,P8课程带着你帮你搞定。有人说我非常的特殊,我不仅我想学整个开发,我还想学测试,想学这个运维等等。OK,我们所有的帮你定制出来,一些课程帮你搞定。好了,这就是我们课程的一个特点。
29:03
那有同学可能会说,老师效课程效果怎么样?呃,在我给你详细解释课程之前啊,其实还是拿效果说话好吧。还是拿效果说话就行了啊。啊,又更新了一些内容啊,挺不错的。嗯,每天呢,我们基本上都会收到学员的一些个正向正向反馈啊,当然有些同学比较内向啊,懒得跟我们说他取得的成就,其实真没必要啊,在这里面呢,基本上学员的隐私信息都隐去了,但是聊天记录都是全部都非常的真实,支持你做任何的被调。这是这是最最新的,这是学比昨天昨天看到的更新,这是干了两个半月,长沙涨薪5K。呃,虽然他原来的薪水不是特别高啊,这个最近拿到offer涨了5K,月薪13K。
30:00
当然这东西呢。他原来的薪水不太高,所以让他涨起来太简单了,呃,体现不了我们课程的水平。
我来说两句