00:01
那各位同学,我们继续那上一讲呢,我们呢。给大家介绍了什么是cns,比较比较快,Compare and set,那言下之意,这个所谓的是分两步,先比较后。决定交换是否成功。那简单的。花一分钟再啰嗦两句,复习一下。首先。真实值。原始值是多少?说白了,现在这个线程第一次从主物理内存拿到15。他进行一系列操作以后,可能他要把它从五改为2019。那么这个时候的话呢,它呢是有首先去看看主物理内存的值有没有被其他线程。回写过,那么也就是说白了有点类似于大家SVN和github上面的版本提交号,那么在我之前有没有人动过那么。
01:01
没有人动过最好,那么这个时候导致什么呢?在。对象的内存地址里面。某个值,我的真实值是多少?期望值是多少?如果真实值和期望值相同。比较为错,那么我们在能够进行set set为你更新的值,那么所以说这个时候你呢,就是。处可以修改为2019,此时主物理内存的这个值就已经从五修改为2019。那假如说再来做一次另外一个线程,他之前拿到的快照是我回来一比,我希望。在我之前,没有人动过。但是抱歉。目前。真实值已经变成了2019,我期望值是五,2019和五肯定是不相等的,那么。
02:00
比较。失败,所以说此时他想把它写为201024,这步操作将会变为force,那么这个时候得出当前的值还是2019不变,那么。他所要做的事儿只能是放弃之前的操作。重新从。我们的。主谓主物理内存里面读取最新值是2019,在这个版本的基础上再进行自己的修改,直到成功为止。那么说白了就是一句话,比较并。交换,那说白了,它所要干的事情就是说真实值和替换值相同,就改乘高。真实值和期望值,不想逃。修改失败。好,那接下来。第二问。同学们,如果你要说cns,再次强调看。
03:00
杨哥,这次花那么大的代价哈,给大家讲这个,甚至有些题目是很难,大家听着呢,也都非常的皱眉头,不容易一点点消化,但反过来讲,好老师我懂了,哎呀,值相同。能改不相同,不能改,玩火比较并交换嘛,我懂了,就一句话,真实值期望值相同,比较成功可以交换,然后设置成新值。巴拉巴拉跟面试官这么一说,OK,兄弟,你用过compare也知道CS了,这个方法会用了,底层原理呢?你可别玩了。为什么要用CS而不用NCH?现在你会用了,知道是什么了,这就是杨哥说的学习的第一个境界。API调用工程师,至少你会用,那么底层原理呢?Lawyer。说说。说白了,这个时候你只需要说两句话,第一个,底层原理。自选锁。
04:01
第二个Una讲完了。但是同学们是不是又一脸懵逼了?不要着急,先把根子整明白,以后我们唠唠Una。来,兄弟们。之前使用过一个以后。我们是不是一直在之前用过这么一个get and,就是做前面by tell那个I number加加那个事。好,那么下面它凭什么用这一个方法可以不加S也能保证原子性?没有出现加错,我们怎么加那个值啊。都是2万。20个线程,每个线程操作1000次,有印象吧,同学们。好,那么接下来我们来开始。那。它这个底层代码什么叫unsafe,什么意思呢?我们不妨来看看我们这个方法,它到底有什么神奇的地方,可以不加size。
05:05
解决了我们的number加加、I加加在多线程环境下面的什么线程安全问题。此时。点开我们搂一眼这个方法,其实底层掉的是unsafe类,有个get and。ADD in this value of that。那不用讲。这个一是因为按照原子性的每次增加多少一个,那么说白了就是我调你一次我就增加个一,调你一次增加个一,而且这个一大家可以看这个数字是不是固定写死啊。那么好,同学们,这个this和value of that是什么意思呢?那么注意。这句话干脆这样吧。那杨哥,为了让大家更加的清晰和透彻,我这直接干了这么一句。看着。
06:01
我们都明白啊。现在我们是靠这一个方法。解决了。I加加在多线程环境下面对吧。现场安全的问题。那么首先。咱们在这说清楚了。This,什么鬼?那么来,同学们。这个this哈,我这写远一点吧。那么呢,代表的是什么鬼呢?就是我们的。当前对象。好。那么这块。那么这一个value of that。它又是什么意思呢?那么这一块。请注意。这个东东叫内存。偏于亮。
07:05
内存。天一亮。那么。说白了就是内存地址。他这个的意思哈,那么这块同学们。我们这边。This是当前对象,这个是内存偏移量,这个一固定解,那么它的底层代码我们再发。当前对象value of that内存地址,说白了它的意思就是当前这个对象,这个内存的地址值是多少,好,再来往下发。我点。现在又是三个参数。刚才是不是也是三个参数啊,说白了。Object当前对象。然后。那是内存地址。Int I固定时间,但是注意请看此时已经跳到了unafe.class。
08:03
那这货到底是个什么鬼啊?那么这个时候我们呢,非常抱歉的告诉大家。这个里面一般你找不到,你得跑去我们的GDK里面。然后大家看。在我们的礼包。以及我们对应的干嘛价包。下面我们可以看到。这一块力部,那么在这块是不是有个RT点价,我们讲GVM的时候说过在内的加载机制,RT点价是runtime运行环境,那么这个时候请大家露眼。不多废话,我们可以看到这有一个散。这又有底下的一堆堆,那么是哪一个呢?同学们?这个时候请大家回到我们的安内,请看报名。上。
09:01
Michael,这个东东请注意。Dog。这。是不是有个Una加class?那么也就是说它根本是什么?GDK自身携带一个最出娘胎,就带着一个最基础的类。那么这个类。目前我们漏眼是不是大部分都是native的方法呀?那么好,源码级别的讲解来了,兄弟们,这块有点吃力,有点费脑,请大家集中注意力,大概十多分钟突破这一关,下午听课有点困,咬咬牙坚持一下哈。那么基本上。爬坡的路都不轻松。那么这个时候。熬一下。你打开以后。刚才看过正源码,那么这个按C类是什么?RT减88里面上。Michael,下面有个unsafe,那么这个时候同学们请跟我来。
10:05
首先。我们再看一下autotomic in这个原生类,你这有个unsafe.get unafe首先得到这个类,那沿下支线再来看它这个里面是不是有个private。Verlatile value知道为什么我们前面一道题目要详细的讲解verlaile,很多同学都喜欢装逼说,啊,没事,我看看源码就行了,你看源码你看得懂吗?你知道人家什么意思吗?那么这事呢,干嘛呢?我们回到我们这个类。这一步说白了,这个方法其实底层掉的是这个,那么这个方法来自于哪?来自于unaf,那unafe什么意思啊?大家请看3MICHAEL克这块,那么Una完了以后得到它这个东东,它的意思是对象的field ofset,那么这个offset就得到我们的什么这个对象地址在这个位置的内存偏移量。
11:03
那么言下之意,同学们。只要我们的in teacher。Atomic integer。这块是个value的,我用它修饰,我每次做I加加或者加加I的时候,只要一变化,是不是其他线程都可见,好,那么接下来请看。首先它是CAS的核心类,CAS是比较并交换,那你凭什么能保证原子线靠的是底层的UN safe类?你要这样回答给面试官,他是来自于哪?来自于?GVM的2T运行架包里面出娘胎就带着,我们用的是最底层这个类。那么这个时候由于Java是无法直接访问底层系统的,那么换句话说是什么概念?只要是native修饰的方法,Java无能为力。那么大家在学GVM的时候学过一个什么native stack本地方法站?
12:00
那么相当于Una是上当时到家的时留的一个后门。那么它可以直接操作特定内存中的数据。按C类存在于这个包。这个包的作用就可以像C指针一样操作这个内存什么意思啊?Value of set叫内存地址偏移量,那么言下之意,我就是告诉你一个坐标,比方说现在这个教室里面第三排、第四列座位的这个同学,请你站起来,我就是不知道你的名字,但是我知道这个内存地址我是不是可以直接操作你。那么这个时候能够直接操作地址就是C的指针,这是最底层的,最厉害的,不会错再来。注意,CS执行依赖于UN类的方法,那么言下之意,UN safe类大家已经看了,这是不是有很多native?那么大家露眼那么欧了,这事我们往下翻。所有方法大部分呢,它都是AT5修饰的,也就是说按C中的方法都直接调用操作系统的什么底层资源执行,首先我们得到第一个结论。
13:07
原子整形它之所以在I家加重操作,在多线程的环境下面不用加S也能保证线程安全,是因为。他用的是UN safe类,这是第一步,那么这个UN safe类牛逼在什么地方,他怎么能搞定呢?大家请看。变量value of set表示内存中的偏移地址,就是我刚才所说的这个教室第三排、第四列的同学,给我站起来,我可以不知道你的名字,但是按类就可以根据内存偏移地址获取数据,极度的精确。那么刚才在这。写过this,就是当前对象value of set,就是当前对象的这个地址啊,就是我们的第三排第四列,这个同学给我站起来,然后我要对你进行干嘛加机的操作,那么这个时候请看第三步是这个好。
14:01
研究了安类,那么我们就要来说说我们的什么CAS到底什么情况。来。CAS,它属于比较并交换是。一条CPU并发源于,那么沿下支线干嘛呢?它的功能是判断内存中某个位置的值是否为期望值,那么大家能不能理解这个value of set,这个内存偏移地址是什么意思了吧?那么言下之间,如果是更新,不是force不更新,这个过程是什么原子的,也就是它底层是靠的是unaf这么一个类来保证原子性。那么来。JVM会帮我们实现出cns的汇编指令。这是一篇硬件了,那么这是一种完全依赖于硬件的功能,通过它实现了原子操作。那么呢,CS啊,是一种系统源语。
15:01
原语属于操作系统的用语范畴,是由若干条指令组成。完成某个功能并且什么的,什么叫原语?就是这的CPU并发原语的简写,就说这些原语的执行必须是连续的,中间不许有人打断,我是最底层的。那么言下之有有点类似于假设今天是。的车队。五部车同。出来,你们觉得有可能有哪个车加塞加进去吗?这是不允许打断了,这叫允许,所以说在执行过程中不允许被中断,不被中断代表是不是必须要等我操纵完了,别人才有机会拿干嘛?习大大。车队过去了,解除交通封锁和交通管制啊,那么言下之接,这是一条CPU的原子指令,不会造成所谓的数据不一致啊。我们把这句话翻译出来就是说明什么,是不是就是线程安全?听懂,所以说同学们请看。
16:02
老师再把源码再从理论讲明白,先从理论咱们再到源码两步,最后小总结,共三步来回答。第一个理论CAS是什么?它凭什么能够保证原子性?是因为靠的是CS的汇编指令发出。CPU原语偏硬件这种东西天生就是连续的,不会被打断。第二个,我们来看一步一步的抠。第一步我们用的这个方法,我点。第二步我们是用按shift类,按类现在已经介绍过了,是RT点加包里面的原生类。第二步,我们再点开get and ADD,在UN safe类里面过来用的是get and ADD这个方法,那么这个方法的底层源码是什么呢?一般的同学。他没有公开这个源码,你去点不大方便,那么这个时候老师跑出来。
17:04
这个方法底层是它,这个方法底层是它没问题吧,但是接下来。请看。Unsafely get and ADD it。这个里面VALUE1就是这个对象,这个对象就是这个this this,二就是这个L,这个L就是上面的value of set,内存地址偏移量,就是我刚才所说的第三排,第四列这个同学的位置。Y64就是I,这个I就是每次加个一,请看。我们没有通过枷锁,关键核心源码CS。它的底层源码是什么意思啊。首先int value等于五,我们看get and什么意思,是不是先获取再加?所以说请看do y呀,它这个循环啊,同学们注意什么意思呢,首先度。
18:06
二话不说先上来,为什么要先做?因为get是不是在前面实先获得啊?This,当前对象。Get in value time,你看加了这种一个方法什么意思呢?VALUE1是它,VALUE2是它,那么这个VALUE61是不是就是这个Z,这个VALUE62是不是就是这个内存地址偏移量,它的意思就是说兄弟们。当前对象VALUE1就是这个VALUE2就是这个地址,你给我告诉我当前这个对象这个地址上的值是多少。Value明白,所以说这一步就是解决。Get。这个操作明白吧。然后。我先得到了,就是我说的这一步,有点类似于这个线程,先从主物理内存。
19:00
得到了一个值,拷贝到自己的本地线程的工作内存里面。第一步同学们能不能跟上?好,第二步干嘛呢?比较并交换。啥意思呢?如果。过了一会儿。当前对象。这个地址的值。跟我们的VALUE5是一样。那么我就要。加个一。能跟上。就是,这就相当于有点类似于VALUE61就是当前对象,VALUE62就是值,当前对象的这个内存地址值,如果也是VALUE65,我们这是不是得到五,言下之意是不是就是我手头上拿的那个快照的那个值,跟我这个地址里面的这个期望值刚好是一样的,那么我就修改听懂了吧。那么好,沿下直线,如果this DR compare and swipe,这个方法返回的是错。
20:03
处又取反,整个返回的是false,那么你告诉我,说明我修改成功,我是不是跳出这个循环?返回能跟上,但是假设我这个东西已经被人改过了,不好意思啊。当前这个对象。这个地址上的值。但这个VALUE5相比,如果不是。那么抱歉。这个方法返回false,那这个方法返回false,前面又加了个感叹号,取法false,取法是不是错,那么这个Y这个整体是不是就是一个处。那么干嘛又来一次循环?也就是说,假设在我之前已经有人动过了我目前的。快照值和物理内存。这个对象的真实值不一样。抱歉,我比较失败,没法修改,只好重新再再。
21:04
这个对象的这个地址啊,拿到这个最新值听到再来进行比较一次啊,直至比较成功,我才能够收工,否则我在这儿是不是就一直循环着。同学们,这一块清不清楚?好,那么这个时候我们再细细的讲一遍。Get and equipment,它的底层其实是CS思想,靠的是按safe类的CPU指令原语来保证原子性,也就是说原子性套的是Una。那么。做工作的思想,底层思想是CAS CAS是比较并交换,那么说白了,真实值和期望值相等。交换成功,修改值成功,真实值和希望值不一样,失败,那么失败了怎么办?失败了再来一次,所以说这有个do外啊,我们再来给同学们再慢慢的讲解一次,不要着急,这些知识本身就难,那么请大家听得懂的地方你仔细听,听不懂的地方请你硬着头皮听,我不废话,因为阿里巴巴蚂蚁金服考了。
22:15
你要想进大厂,现在缩招了2019年,要么成功,要么更加成功,没有第三条路。坦白讲,你在上硅谷学习也只有三个选项,要么忍,要么狠,要么滚。不要跟自己说,学不懂这块是挺难的,再听杨哥讲一遍。Get and increase方法底层调的是按A类的这个方法传三个参数,当前这个对象,这个对象的内存地址。然后干嘛?这个对象的内存地址底层调的是CS思想,如果比较成功了,加个一,如果比较失败了,再重新获得,再比较一次,直至成功为止。好,我们过来。
23:04
认识。就是这个VALUE1 value of set就是这个VALUE2。V4就是要准备修改的,那么一是什么意思?是不是就上一个基础上加个一,比方说A加加嘛,当前这个值是五加加,那么就是六加加那么就是七加加那么就是八,所以说过来。一开始,我要先get。先给我告诉我现在值是多少,那么好,我必须要先得到最新值,那么过来当前这个对象,Value z value,二是这个value of set,内存地址偏移量。三排四列那个同学给我站起来,就是这个意思啊,三排四列这个地址啊,假设现在的值,我们得到的是什么鬼,是初始值啊,我好。那么现在。当前这个对象compare and swap是不是交换的意思啊?Int干嘛呢?假设我们当前这个对象,说白了,当前这个对象什么意思啊?当前这个对象就是我们现在这个值啊,它的默认值数是五啊。
24:05
好,那么呢,当前这个对象在Y62这个地址的值里面,现在Y6值是五。初始值是不是五,没问题吧,我们过来。如果说过了一会儿我们去比较,那么呢,当前对象这个地址。还是不是五,如果是恭喜你,干爽死你了,我们才能做后面的操作干嘛,那么是不是就是五加个一,那么最终是不是会变成六啊,那么好,如果比较成功了,那么this。到这儿是错。处在前面取个反while里面的这个整体是false,说明刚好我运气比较好,没人动过一次就成功了,False我跳出循环,我们就return这个VALUE5,就是刚才的这个VALUE5。好,因为我是先get再加加嘛,那么也就是说get我是这个五,但是GET5的同时,我已经是不是把下面已经加成六了。
25:06
好,那假如说反过来。不好意思啊,当前这个值我获得了以后,有的别的线程比我更快,捷足先登了。那么呢,这个对象这个值我期望值是多少,但是现在真实值跟我的期望值这个VALUE65这个位置这。没有一致。比较失败,那么这个时候从this到这儿就是false false在前面加感叹号,取个反整个Y啊,是不是就是错干嘛,说明我这个循环。不OK。重新被拉回来再执行一次,因为别的线程已经在我前面改过了,我的真实值和我的期望值一比较是负啊,再过来当前这个对象在这个地址最新值是多少,然后再这么反复的比,直至比较成功。OK,好,那么这个就是我们CAS它底层的比较原则,那同学们能不能跟上。
26:09
好,不要着急,就担心同学们听不懂,老师再讲第三遍。难点就是这个。Get and ADD,那么它有三个参数。Get and at,老师在讲第三遍,非得给我整明白,杨哥讲课只不过跟着我学比较累,比较难,但是你的内功会被我逼出来,必须懂,你在我手下就不要弱。好,我们马上讲第三遍,不要着急,现在CS的底层原理,这是干嘛?给大家首次知道深度的UN safe类。
我来说两句