系列 1:P46:50w年薪面试题:5:所谓的锁升级其实就是对象头信息的变化你明白吗? - 马士兵官方号 - BV1mu411r78p
但这个问题呢实际上是那个cs里面比较简单的问题,这个问题是cs里面比较简单的问题,我们说一个cs里面比较复杂的问题,我看看我看看这个难度能不能给讲给大家听,听我说,看这里啊。
这个cs里面比较复杂的问题是这个,那么这里是个八,我们把它读过来,读过来之后呢,呃呃读过来之后呢,我们我们把它改成九九,写回去的过程呢,实际上是我刚才写了一个维码,这个维码叫做if,你哥们儿。
你是不是依然等八对吧,如果你依然等八的话,我把你改成九,那我想问你的是,如果在这个这个过程之中,比方说我判断你确实依然为八,我刚判断完,我还没有来得及把你改成九,然后这个时候你用九把12给覆盖了。
你不又把别人的值给覆盖了吗,来能听懂这个问题的老师可以,对吧,所以cs如果你想解决问题的话呢,你你你起起码保证一点,就是说这个玩意儿一定是要是原子操作。
是不是你就是你这个最底层的这个操作必须得是原子操作,大家有的约会可能会说了,对,这个就是原子性吗,嗯就这两这两个必须中间不能被人打断,那他是怎么做到的呢,这个也是这是原来阿里阿里是面试的一个问题啊。
这个不跟不是说事事听啊,提阿里,这就是他面试的一个问题呃,为了解决问题呢,实际上整个过程比较复杂,我讲给你听啊,我一点点讲,你别着急,为了让你理解这个问题,我们可以考虑去读一下jdk的源码。
通过jdk的源码来解决,呃,你想读这个cs的源代码呢,我建议你,可以读这个类,这个类呢叫做atomic integer,atomic integer,呃,像我刚才讲的举的那个例子啊。
那个对于一个对于一个一个数字来说,我们好多线程呢都对它进行加加呃,我们要想保证数据的一致性,除了用锁之外,我们还可以考虑用用它用原子类叫原子的integer,atomic injure,什么叫它。
为什么叫atomic integer,就是在这个integer里面,它所有的方法都是可以保证原子性的这个意思,所有的方法都可以保证原子性,就是中间你不用上锁,也就是说你看这儿看这儿。
我最开始的时候有一个can呢,它的初始值为零,呃然后呢我这里呢有一,个方法m在这方法m里面呢,我给这个count加了1万次,叫increment and get,就是它的一个方法。
类似于count加加好吧,然后呢我起了100个县城,100个县城,100个线程,然后呢每一个县城的那个让他执行一遍啊,然后等他结束最后的结果呢,当然它一定是100万,为什么呢。
由于atomic integer内部全是原子性的,你不需要上锁,所有的结果一定是正确的,这小程序比较简单,呃,我我我我就我就不在这过多解释了,可以吧,还可以继续给老师扣一,我们主要探究的是什么。
主要探究的是tn地址,在没有上锁的情况下,没有用synchront的情况下,它到底是怎么实现的,对不对,好看这里,看你们问的这些问题啊,叫老师现在用的这个什么时候编程需要,第一你面试的时候必须需要。
第二,如果你想写那种高效率的,比方说抢票的这样的软件,他就需要买票,不可可以不使用分布式锁吗,如果你的票数很简单,当然可以不使用分布式嗯,分布式项目,分布式项目这种分布式的锁嘛,这个不难嗯。
atomic不就是用cs吗,呃这不是废话吗,我现在给你讲的不就是cs原理吗,老师现在用的是什么编程语言,这个编程语言不就是java吗,好看这里啊,我们aaa omic engineer。
然后呢我们我们看到的这个就是,这个atomic imager他在不上锁的情况下是怎么能做到原子性的,好不好,是马老师吗,可以试啊,咳咳咳,嗯,声音这么磁性,声音明显很雄性嘛,看这两个好。
我们继续count their increment,and get好,我们点进去,我们来看看这个背后的代码,它到底是怎么实现的,结果你会发现呢,哥们儿使用了一个类,这个类呢叫unsafe啊,叫不安全。
可能return on safe,点get and and it好,我们再点进去一点点看,当你我们点到这里的时候,你会发现它使用了我们unsafe里面的另外一个方法,这个方法叫什么。
叫compare and swap,and出现了我们熟悉的cs,看到了吧,好我们再点进去,结果很不幸的是,你会发现这里到了native,ok不是你们在聊啥,我的天,来来来来来来重,新来一遍啊,看这里。
为了探究atomic energy为什么可以不使用synchronized也能做到原子性,我们去看它的源码,count the increment and get,你会发现我们调用到了unsafe。
get at end,你会发现它调用了unsafe compared sweat,and也就是cs的方法,结果很不幸的是,当你读到这个方法的时候,它变成了native,native是什么意思啊。
native就是c和c加加的代码嘛,对不对,native是c语言或者c加加语言实现的,那好,那我们就看看c和c加加的代码好吗。
因为我们毕竟得追求。
高薪嘛,好如果你还记得的话,我们用到的那个,那个lay叫什么来着,java类叫unsafe,好对应的jvm源码里面就是这个unsafe,点ppt啊,sorry,点c p p p p t了,unsafe。
cpp c加加代码,那我在这个c加加代码里面,大家还记不记得他用的是哪个方法来着,叫compare and swap in,对不对,他们搜一下。
好看这里这里就找到了我们unsafe compare and swap inc,加加方法好,讲到这儿还能跟上的,给老师扣一,c plus plus这个什么软件。
我都不知道你们在关注啥,这什么软件很重要,不就读个c加加代码的软件吗,sublime嗯,然后呢我们要稍微读一下,就是它里面到底是怎么实现的,其实呢你其他的我全部给你略过,我们主要看最细节的代码就可以了。
代码在这,实际上它调用的是atomic这个类原子c加里面那个原子类,compare and exchange方法,那好那这个东西在哪呢,好我们点过去,我直接给你点过去,就在93号。
最终我们找找找找到了这个方法的最终实现,也就是我们atomic energy最终靠的就是这个实现好,这个实现是怎么实现的呢,你往这儿看,这里面有个简单的判断。
他说首先判断你os e m p这个呢我就不给你看源码了,mp这件事特别容易解释,它的全称呢叫做,multi,persons是吧嗯,多人运动哦,sorry错了,重新耕种啊,猫体,processors。
多处理器就是说如果你的机器上有好多个处理器,好多个盒,那么它最终的实现是怎么实现的呢,是叫lock if mp,这就不用我解释了吧,就if mp,如果你是多核,前面加一条lo,最后呢是有一个这个玩意儿。
这玩意儿是什么东东呢,这个玩意儿是一条汇编指令,compare and exchange,通过这儿你可以看到哦,原来在我们的cpu级别,在我们的汇编级别。
它就有一条汇编指令叫compare and exchange,如果这事你理解不了的话,画个图你就理解了,这是一颗cpu,这是一颗cpu,这是我们内存里面的某个数据里边写了个八,我的cpu有一条。
原始的指令可以用cs的方式,也就是compare and swap的方式来改,这个八cs方式怎么改呀,把八读到这个cpu里面来改成九,往回写的过程之中会比较八,你还在不在,如果你还是八,我就把你改成九。
如果不是我,我再重新读,能听懂吧,这就是这条指令的含义,这是一条汇编指令,这是从宏观层面,从微观层面都是一样的,来这块儿还能跟上这老师课印,那我当你对他就是底层的自选指令嘛,但现在的问题依然是一样的。
依然是一样的,就说这个问题啊,哥们儿,你是不是原子性的,如果你要是原子性的,我不用做任何操作,无所谓了,就是吧,你只要原子性的哦,我就明白了,原来是atomic。
到最后无非就是底层有一条原子性的语句给他支持了嘛,就这么简单嘛,对不对,好听,我说这个呢如果你去查英特尔的汇编手册,它会明明白白的告诉你,这个东西不具备原子性,原子性的,没有啊,不对没有。
那么到底怎么样才能让整个语句能够做成原子性的实现呢,它的奥秘就在于前面那种lock if mp,那好look if mp是个什么东东呢,我们点过去,其他的你不用管,你只要看这条指令就可以了。
lock if mp是当你有多条,当你有多个盒的时候,在后面的汇编语句的前面加一个lock语句,也就是说,也就是说最终的atomic的实现叫lo compare and exchange。
我给你写出来了。
这是轻量级锁的自旋,从我们从atomic integer啊,我们读到了unsafe啊,我们又读到了unsafe,点cp啊,我们读到了,lock compare and exchange,好了。
这是这条汇编指令,也就是说我们所有的自旋锁最终的实现全是它来这块能get到的,老师可以,当然一般来说面试题问到这个程度,这个深度就差不多了,呃不过呢有的面试官还会继续往下问,说为什么洛可能实现。
为什么lock能实现原则性,lock能实现原则性的原理,这个还要听吗,还要继续往下听吗,还要听到口音了嗯,好听我说,洛克为什么能实现原子性好听,我说呃。
一般来说最简单的是说当我们做后面这个汇编语操作的时候,lock会锁总线,这是最简单的实现,这也是一般cpu的实现,我再说一遍,这是一般cpu的时间,什么意思,这是一颗cpu,这是一颗cpu。
我们总是要通过这条总线,对不对,通过总线去访问内存这个吧,那么当我这个cpu做什么操作的时候呢,做这个操作的时候就改了个八的操作的时候把总线锁住,锁住的意思是说只有我能在上面传数据,其他人谁也传不了。
听懂了吧,那这就简单了吗,反正别人也传不了,那我先那个锁锁了之后,然后改改完之后再说好了,这是一种当然其实现在当然当然你可以想象一下啊,就是说如果说cpu锁总线的话,这是cpu,就是cpu。
你把总线给锁了,那等于其他cpu谁也用不了,能不能理解效率太低了好,那这时候怎么办呢,其实往往上往往这时候我们用的是什么呢,是锁,保存行,是锁这个缓存行,ok,什么叫损,不过这里要跟你解释缓存行。
又又又比较费劲了,大药停缓存行吗,就是我给你讲就就没边儿了啊,缓存行行吧,我一会儿讲讲讲给你们听,但是呢我这个河水喝的挺多的,那个哪位小姐姐来一下,踢我一小下,我去上个锁,不是嗓子不太好啊。
帮忙上个厕所对嗯,对,行行啊,求求求老师先跟大家聊一小会儿啊,我上我上个洗手间,hello,差点翻了,马老师去个洗手间哈,然后我给大家顶一会儿,我刚才都没有看到这个评论区,我一直自己在那说。
我现在终于看到了,上不上锁嗯,这个你说老板上厕所谁敢去偷看,是不是,反正m是不敢去排队,你们这个技术学得很好呀,生活中随时要用,刚好趁着这会儿人多哈,我再放一下这个码。
今天晚上的这个笔记资料是vip里边有的哈,没有加过小姐姐的,赶紧扫个码,马老师来了,这个码我就得撤走了,然后赶紧扫一个嗯,扫到下课之后,马老师把笔记发给我们,我们第一时间就发放给大家,然后录播的话。
你问一下你的小姐姐哈,所有的资料,所有的录播,所有你想要的东西,这个简历模板,大厂面试题,技术分享资料,职业规划的指导,你想要的一切,你直接扫码加小姐姐,有了就别扫了哈,专业一点,不要做渣男啊。
专业一点加一个就行,然后呃下课了之后直接跟他沟通,对好多程序员,你们都是海王,一个人扫n个,聊得过来吗,小九漂亮吗,小九特别漂亮,你咋的,你要分手吗,你可以考虑一下,可以换一个。
当你的女朋友不支持你干啥的时候,你就把它换掉,扫了啊,大家都记得,扫一会我把码撤走了,这些上面这五个点所有的资料都可以领啊,我把这个拿走,小壮壮好看吗,那就是天仙还好看嘛,你直接跟他聊就行。
马老师回来了,我撤了啊,拜拜,如此的迅速速去而赎回啊,好看这里啊就是这个我今天没打算讲缓存好的,但是大家想听的话,一并讲给大家听嗯,关于混子王这件事呢又比较复杂,我先把ppt打开,嗯嗯,好稍等啊。
嗯就是你,嗯看这里啊,就是关于缓存行呢。
系列 1:P47:50w年薪面试题:6:一个Java对象到底有多大你衡量过吗? - 马士兵官方号 - BV1mu411r78p
缓存啊,缓存呃指的是什么意思,那个缓存呢我先给你解释指的什么意思啊,就是这是这是cpu,这哥们儿速度特别快啊,他就是博尔特是吧,这个内存的内存速度超级慢啊,马老师啊,那博尔特比马老师快多少呢。
大概快100倍,快100倍,那这个事儿就比较麻烦了,那就意味着说我cpu如果发出一条指令,然后去内存里面取一个数据过来,我发出指令之后,我得等99个时间周期,这个数据才能取过来,这个能不能听懂。
所以呢我们想增加取数据的效率,我们怎么做呀,办法特别简单,就是在cpu和内存之间增加一些中间环节,这是北京,就是上海,我取数据取太慢了,怎么办,能不能把上海的数据先放到徐州,徐州的数据先放到济南。
然后北京取的时候先从从济南取,可不可以在中间加几层缓存啊,还有这是缓存最基本的概念了,那好那它中间有几层缓存呢,一般来讲呢从cpu到内存一共有三级缓存,但这里有一有一些简单的数据。
是近几年的测试cpu的计算单元到自己内部的寄存器,大概是小于一个纳秒cpu,内部的计算单元,如果想访问主内存,约需要80纳秒,什么情况,no不会吧,他不会把我刚才,稍等啊,我登录一下我。
我别把刚才记记了半天的笔记给弄丢了,你不要这样地看着我,我给你记了半天笔记,别到时候给弄丢了啊,我先登录一下,ok ok还健在啊,good这就是缓存的重要性,哈哈哈,你说的很对啊。
好听,我说刚才我们讲聊的是这个缓存的最基本的概念啊。
好我们继续聊呃,一般来说呢,从cpu到计算,从cpu到内存啊,中间经历了三级缓存,当我讲到这儿,很多人可能会说,老师这个中间几级缓存为什么不是四级,为什么不是二级,为什么不是一级。
这东西是一个折中的结果,是一个工业上的妥协的结果,集数越多,你要存的份数也就越多,虽然说他访问最近的访问比较比较快,但是你要存的分数就太多了,那么集数越少呢,你访问的速度会稍慢,但是存的分数也会变少。
所以有利有弊,中间是一个折中的结果,听懂了吧,spring 3级缓存啊,这跟这个关系不大啊,别往一起混,这是cpu到内存之间中间有三级缓存,那么这三级缓存呢,分别叫l one l two和three。
那好这个l one l two和three长什么样呢,我们现在的cpu呢多数都是一颗一颗的唉这是一颗唉,这也是一颗在一颗cpu内部往往有好多个盒,这是一个盒儿,这又是一个和好了。
一般来讲我们的l one位于核的内部,l two呢也位于核的内部,而l three我们位于一颗cpu,多核共享,然后多颗cpu共享内存好,这个图能看懂的,给老师扣个一,相对简单一看就能理解。
但是现在我向你提个问题啊,我们现在的运算单元现在要找一个数值i,那么根据缓存它的理论,他首先去哪里找呢,首先去l一里面找,那l一里面有i吗,去内存里面找这个i,假如它是八好,这个班呢往l3 放一份。
往l2 放一份,往l一放一份,放到寄存器开始做计算,那下次我再用到这个i的时候,我是不是直接l一里面就有了,比如说我for循环1万次,对于i加加我,用得着每次都去内存里面读一遍吗,没有这个必要。
我只要从l one里面最近的那个缓存里面找到就ok,那这样第一次骑上是不是更慢了,是的,有利有弊,是这样的啊,好了同学们来这块能听明白的,给老师扣个一,那现在又来第二个问题啊,就是说同学们你们琢磨一下。
我们取数据的时候,是我们用到一个数据取一个吗,比方说我用个布尔类型,就一个字节,我就把这一个字节弄进来,那我想用这一个字节旁边这个字节呢,那不好意思,又得来一遍,从121~23到,然后再返回去又来一遍。
那为了改进效率,我们可不可以这样做,就是当我读这个数据的时候,把它周围的周围的数据一块一块的放进来好实际当中也是这么做的,这样做的话呢会提升效率,比如说我们对一个数组的循环,如果你不能,理解的话。
这是一个数组,对一个数组循环,我们取到第一个,我们顺带着也把它周边的一块往上放进来,放到l3 里,放到l2 里,放到l一里,那我们当我们对这个数组进行循环的时候,我下次再找这个数组的第二个值。
我就不用去内存找了,我这就直接找过来了,对这个被称之为空间局部性原理啊,没错说的很对,来这块儿能听明白的,给老师口音对象都有锁上,你还讲吗,其实跟锁是这这个跟锁是息息相关的,我们一块穿过来的啊。
我们讲这个lock lock所缓存缓存行锁什么东西,就是锁这个,当然有有有同学可能会说,老师啊,那这个大小到底是多少呢,就是你你你你把这块数据读过来,这块数据到底是多大呢,是不是越大就越好呢,未必。
如果你的数据特别大,那么每一次读过来,虽然你命中率很高啊,你你访问多数情况下都在l one里呢,但是你往l one里装数据的这个过程就太费劲了,因为你数据量数据很大,另外呢如果里边没有的话。
你得用用别的一块数据把这块给替换掉,太费劲了,那如果太小呢,如果太小的话,你命中率不高,每次找都得从内存拿一遍,所以又是一个工业,折中的结果好,最终的这个数据是64个字节,好吧。
来这个呢被称之为一行数据,一行数据啊被称之为缓存行,好了,这就是缓存行最基本的概念,而one和out two有什么区别,一个慢,一个快,一个大一个小,就是中间在济南和徐州中间加了一层而已。
没有什么太大区别,嗯那这块能听明白了,我们就来琢磨一件事儿了,我们位于同一行,在一个行里面,当我一颗cpu要用x值的时候,我们会把这一行数据从这里读进来,从这里读到l3 ,l3 ,读到l2 ,l2 。
读到l1 ,这个没问题,对不对,那如果说我另外一颗cpu啊,这颗cpu它用到了这个缓存行里面的y数据,那他用到y的时候,同学们你们琢磨一下这个y的话,是不是也得把同样一行读过来,读过来读过来。
那现在问题就在于,当我把这个改了之后,我要不要通知另外一边说这个,x已经被我改了,来这块能听明白的,给老师扣个一,就这里面也会涉及到同步的问题,那要不要呢,要还是不要是要的,不用啊,有的时候不用。
有的是说要这东西呢是取决于编程,如果你程序上要求说你必须通知,那么他就会通知,如果你程序上不要求仔细听,仔细听,我说,如果你程序上不要求,那么这个时候是通过一种机制来自动化的完成同步。
这种机制被我们称之为叫缓存一致性协议,好这个词儿我觉得应该都听说过,对不对,缓存一致性协议应该都听说过吧,听说我给老师扣个一好吧,无所畏惧,说敲完msi错了,那个那个不是不是。
不是那个那个那个那个只是缓存一致性协议的一种协议啊,我们要精确一点,嗯,不严谨对啊,说的很对,我再说一遍,这里头呢跟那个我们自己写的程序里面的锁没有关系啊,就是cpu内部的自动化的机制就是这样的。
就是在它的这个机制里面呢,由于一个缓存行很可能在多颗cpu之间存在,或者多个盒之间存在,那么这个时候就意味着,我们有必要用一种机制来保持它们之间的数据一致性,好这个数据一致性用什么来保持。
呢我们把它称之为叫缓存一致性协议,这个缓存一致性协议,有同学说volatile,这跟volatile半毛钱关系都没有,你千万千万别在这上面犯糊涂,我再说一遍,wallet tel。
缓存一致性协议是196几年就出现的东西,所以缓存一致性协议跟volatile没有半毛钱关系,ok由于缓存行的存在,缓存行存在的时候,就意味着我们必须要用某一种机制,好了好了,你们别在这露怯了,我的天哪。
jeffrey carry,别说了,说的一点都不对啊,这个这个再说就丢人了,别说了啊,看这里呃,就意味着我们必须得采用一种机制,让不同的缓存行在不同的cpu核之间保持一定的数据一致性,好吧。
那好那这种机制叫什么呢,这种机制被我们称之为缓存一致性协议,但是这个缓存一致性协议在不同的cpu之间,不同的cpu采用的是不同协议,就是自己的cpu厂商自己定的,英特尔的cpu被我们称之为叫msi。
而像其他的arm的,mac的,其他的各种各样的cpu,他们都有自己的协议,有的是m o s i,有的是m s i,有的叫synapse,有的叫firefly,有的叫dragon好,他叫什么没有关系。
总而言之,大家一定不能把msi称之为缓存一致性,它只是说它是英特尔cpu的缓存一定性协议,那有同学可能会说,老师这东西跟我们编程,有什么关系吗,展示一个小小的例子,看这个小例子,你要能读懂这个小例子呢。
必须给我记着啊,这缓存一行是多少,一行是多少,64个字节记住了,把这数字先在脑子里过一遍,64个字节啊,那在64个字节里面看这里,在这儿呢我们有一个class t t里面呢只有一个long类型的数据。
这个数据是x,long类型是多少个字节,八个字节,对不对,那一行数据我们说假设一个缓存行能够装多少个浪呢,打个龙好,我们继续往下看,在这儿呢我有一个关于t的数组,这里呢有数组里面有两两个t两个t对象。
这是第一个t对象,这是第二个t对象,接下来我做了一件事儿,这个抗的值是10亿,我用两个线程,线程和cpu的和是一一对应的,我用两个线程,这是第一个线程,第一个线程我对第一个t的x改了10亿次。
第二个线程对第二个t的x改了11次,这是一个小t对象,t对象里面有个x,这是第二个小t对象,这个t对象里面有个x,有一个线程玩了命的改,他改了多少次10亿,另外一个线程玩了命的给他改了多少次呢,10亿。
这是这个小程序所完成的功能,很简单的啊。
那好剩下的这段呢,实际上就是我来计算这两个线程结束到底要花多长时间。
好这小程序能看懂的,给老师扣个一不难,来我们来看一下这个小程序到底花多长时间呢,走你呃,注意啊,这里花的时间是775个毫秒,也就是说我循环这21次,完完事儿之后,796个接近800ms。
但现在我干一件特别奇怪的事儿,你可能以前没有见过的,我把这个打开,我就在他前面放上p一到p77 个没有意义的long类型,在它后面放上七个没有意义的long类型,然后我再跑同一个程序走,你。
这个程序变成了240个毫秒走你240走你240,嘿你还回回都240,241,ok好了,这个就比较好玩了,来你们好好琢磨琢磨,为什么我把它怼上了,七个没有意义的东西,放到前后的时候。
对他的访问反而效率提升了,为什么大家再看一眼,我把这个注释掉,我把这些注释掉啊。
你放心,我把它注释掉,马上变成800个毫秒,看到了吗,原因是什么呀,一次多一行,同行要共享,其实这个程序呢很简单的证明了就是缓存一致性协议的存在,这不知道大家能不能理解啊,看这里,同学们你们想一下啊。
我们说222个t对象,这两个t对象呢在最开始的时候呢,它是前后没有任何数据的遮挡,所以呢这个t对象那个x可以位于这个位置,另外一个t对象的x可以位于这个位置,这两个大概率位于同一行。
那当我们读数据的时候呢,我的第一个线程会把这个缓存行读过来之后,玩了命的改它对不对,然后另外一个线程呢就玩了命的给他对不对,那根据我们刚才所讲的,由于他们两个为同一行,那我对任何这行数据的更改。
我得需要用一种机制通知另外的cpu也,就是说这时候我们的缓存一致性协议,由于我这个我这个是那个英特尔的cpu,所以呢m1 si协议是不是就被触发了,他被处罚的话,他要不要耗时间呀,他一定会耗时间的。
我可以告诉你啊,就是缓存一这个m e s i协议定义是,你往l r r two里面写这个东西的时候,就得做同步啊,当然这是这是cpu级别的细节了,我们先不去管它,就总而言之,由于有这个机制的存在。
我们一边改这个数据的时候,一边还要做缓存一致性,所以我们总的时间就变长了,那有同学可能会说,那老师,那你为什么,前后补上七个,这玩意儿他就不会触发了呢,这个事儿他很难理解吗,我们来看这个简单的说明。
来这是我们的x,我在他前面补了七个long,我在他后面补了七个long,由于我一行数据是多少,64个字节来,你告诉我有没有其他任何有意义的数据能跟我位于同一行,有没有,绝不可能,你想想看。
这是我那个t里面那个数据,这是一个t的t的对象,有另外的t的x能给我为同一行吗,那不可能啊,你这个x最多在这个位置吗,或者在这个位置吗,但是你怎么算也不可能跟我位于同一行的。
因为中间已经够了64个字节了,好了,这会儿能听明白的,给老师扣一,那大家明白这件事儿之后呢,有同学可能就会说说老师真的有人这么写程序是吗,哎不好意思,还真有啊,这个人叫道个理,不知道你听说过他没有。
此人名叫道格里,jdk的作者,linked blocking cue,linked blocking cue。
那个类里面就这么写的,如果你还不能理解的话。
系列 1:P48:50w年薪面试题:7:一线大厂70~100万的年薪你拿的到吗? - 马士兵官方号 - BV1mu411r78p
另外的一个中间件。
这个中间件的名字叫disrupt。
就是他。
它的名字叫做disruptor,你可以自己去查,它是英国一家做贸易做做交易的公司,就是做那个证证券交易的公司l max所开发的一款mq,一款消息处理器,单机版的,它的速度超级超级的快。
他曾经错过一个在开源领域比较有名的一个软件的奖项,叫杜克奖,号称全世界最快的单机版mq,为什么我们讲mq什么叫m q啊,叫message q叫消息队列,对不对,消息队列无非就是一个队列啊。
一个数组或者是一个链表,我们能往里头呢不断的往里头扔消息,还扔满了之后呢,等着消费者把它拿走,这叫生产者消费者问题,那,这哥们儿设计的是一个环形队列,有同学说了。
老师环形队列和这个单向的这个队列有什么区别吗,诶你突然间发现单向队列我永远是需要两个指针的,至少需要两个头,一个尾一个,但是环形队列我只需要一个指针,我只需要指在a下一个位置上就可以了。
下一个位置转满了,那就再指下一个位置,什么时候这个这个位置装满了,等着消费者把它取走,我就又指向下一个位置好了,来这块儿能大概能听明白的,给老师扣一,这叫环形队列,这设计非常的牛逼。
当时是他们刚设计出来的时,候那确实是震惊了开源节,所以杜克讲的也实至名归,当然在这个过程之中呢,他还使用了c,就是这个环形队列,说这个纸箱的这个地儿已经满了满了怎么办,转着圈的等待,知道吧。
他不会去找操作系统老大去等着他,在这儿等,转着圈的等等啊等等啊,等什么时候,你这又空了,我就把你放进去,效率很高,不需要惊动操作系统老大好了。
大家理解了这件事之后呢,我们来看看它的内部的一个实现。
我们刚刚讲的是环形队列,就是这个类的实现,ring buffer,ring环形的buffer缓冲区叫环状缓冲区。
点进去,看当你点进来之后,你会发现这里有一个指针,最开始只在-1这个位置上,下一个位置就是零吗,下一个就是一嘛,就开始转圈了吗,然后你突然间发现哦,原来这里还有特别好玩的p一到p7 。
当然我不跟你讲,你一定不理解这个东西干什么事了,因为这个缓冲缓冲区的指针由于是生产者消费者,所以生产者要用消费者要用多线程访问它是一定的,多线程访问它一定的时候,由于有缓存一致性的关系的存在。
如果它和别的数据位于同一行程的,效率一定就会低,所以我们在编程上阻止他和别人位于同一行,怎么阻止啊,就是在他后面给他怼上,七个long,这哥们儿是个long,八个字节,后面七个long。
56个字节加起来64个,其他人绝对不可能和和这哥们唯一统一好了,因为你是64个字节之外了,对不对,来这块能跟上一个老师,可以,大家会讲到这儿,有同学一定会问,前面呢,你万万万一有数据。
你是你是后面后面没有人根据位于同一行了,那前面呢万一有数据的wave放在这儿呢,这哥俩还是有可能位于同一行呀,对不对,别着急,我们看这个rain buffer。
它的父类是叫做rain buffer fields,对不对,走你remember fields,父类叫做remember padding zoning。
结果你符文发现在他爷爷里面又装了七个狼,那么根据java对于对象的排列规则,他爷爷的数据会排在前面,他会排中间,自己的数据排后面,ok这哥们儿永远不会跟别人位于同一行。
来请把牛逼两个字打在公屏上。
这就是为什么那个,缓存行的存在啊,我只是下去证明了缓存行的存在,三级缓存也s,以及,缓存不同行的,编程技巧,那有同学说了,老师你讲半天了,不是讲了个lock的吗,现在还能回得来吗。
讲着讲着公开课嘛,我们就分分分散,属于是那个很很很开放的这个思维。
就开始慢慢的往上往往上讲是吧,讲到哪儿算哪儿,我们讲logo logo是什么,logo是叫索缓存行,记得,发散性课程对发散性讲课。
log呢叫做索缓存行,也就是说呀原来锁总宪,你所把所有人的这个通道全给锁了,大哥这个太狠了,这个不合适,人家本来不想人家,你访问的是这个数据,结果你把录一录一读,人家去访问别的数据都访问不了了。
这个效率是不是不是太低了,他肯定低,我再说一遍啊,这是这是cpu,这是cpu,你们哥俩去访问内存里的同一个数据八,但是内存人家还有别的数据呢,您您您老人家在这个这个cpu在访问这八的时候。
把这路全给堵了,我这个cpu想去访问别的数据都访问不了,能不能听懂,所以我现在改成我只锁定这一行,就锁这行好吧,对我就锁我自己的数据。
我不占用别人的数据,好了。
所以我们效率是提高了lock,这是它的底层实现。
我们再往回,因为我们从脑袋开始讲锁,讲重量级所讲轻量级锁。
讲那个交给操作系统的重量级所讲给自己管理的cas自旋锁。
我们再往回还能回得来吗。
我们得回到这张图上了。
好我们再往回再往回的问题,现在我们讲了两种类型的锁,这种类型的锁呢叫cs,这种类型的锁叫重量级,注意这个重量级未必不是cs,这个重量级只是交给操作系统老大,本来这个里面全是jvm自己管理。
这是gm自己管的o然后呢,您老人家要是交给操作系统老大,那不好意思,这个就叫重量级,因为你需要经过中,间人他就一定会中,你自己管就要轻得多,那自己管这个过程和重量级锁,这个过程。
我们你仔细想一下阿里的一个问题,为什么我们有了轻量级锁,还需要重量级锁,能不能听懂,来我把这个问题写出来。
为什么轻量级锁可以解决同步问题,自选吗,但是也需要重量级所有的存在,y原因是什么,一直自寻,他也不是个事儿啊,唉这大家伙脑子都在线啊,不错对,这里面没有跟大家交代重量,你所有一个最重要的阶段。
这个重量你所的阶段是什么呢,重量你所有一个最重要的它的机制啊,叫做排队,注意轻量级锁自旋是不排队的,什么叫不排队的呀,这个,有一哥们儿在里边儿坐着,比如说是如地如底在这坐着,然后你像其他什么海啊,坑啊。
石头人啊,爱拼才爱赢才会拼呀,来了来了之后干嘛呢,转圈儿,拎着裤子赶紧转转转转转转转转转转转转,然后谁先发现rudy出来了,谁就赶紧进去,他是不排队的,不排队,ok那不排队不排队的意思是什么呢。
它就它就是一个while循环,它是要消耗cpu资源的,while循环也是一种语句啊,它是需要消耗cpu资源的,它是一种循环,那我们所谓的重量级所在操作系统的某一个阶段上。
它是要进行现成的排队指的是什么意思呢,就是这个县城在抢不着锁的时候来给它一个队列,你去里边给我等着,什么时候我叫你,你再出来,等着叫你再出来,等着叫你再出来,我想问你当一个县城在这里等待的时候。
也就是平时我们所调用o。weight的时候,不知道你现在能不能理解这个,weight的含义了,当我们进入这个这个这个里面等待的时候,它需要消耗cpu吗,它不需要,什么时候我cpu说来。
小伙子你出来走两步,你才出来消耗cpu好吧,曹玺总说,轮到你了,来来你出来走两步,ok他才出来消耗cpu,来这块能听懂的,给老师扣个一,我给你讲所的本质,同学问你们有没有印象。
我们写我们写写写写程序的时候,我们说synchronized,t然后我们往往有的时候会使用t。weight方法,有印象唉,所谓这个t。weight是什么概念呢,什么概念,t是一把锁,刚才我说过了。
他脑袋上的改变,就是那把锁和这把所关联的,有一个队列,所谓的t。weight指当前线程,进入队列,wait就直接去排队了,等待什么时候,我叫你t点,notify。
指的是我这把锁上的队列里面随机叫醒一个线程,这个队列是在哪里,这个队列是在jvm的c加加代码里,好刚才讲的这小段能听明白了。
给老师扣一那行,那现在你回答阿里这个问题,可以随机叫醒,也可以特定叫醒,就看你程序怎么写,来回答阿里这个问题,y我轻量级锁也可以解决这个问题啊,为什么需要重量级,在什么情况下用轻量级,用清。
好其实超级简单,你们想这个事儿就行了,现在如在里边儿干活儿,干得不亦乐乎,然后呢,肠胃有点不好,一进去就半小时,外面等了1万人,1万个县城拎着裤子在这里使劲转圈儿,cpu还要在线程之间来回切换。
你告诉我,这个时候我们用自旋锁合适不合适啊,他当然不合适,太消耗资源了,线程数量多,等待时间长,这个时候不适合用自旋锁好了,如果说我们这1万个县城,这时候我们怎么办,等的时间那么长。
1万个人去排队去放到队列里,没有关系啊,什么时候rudy完事了,来喊一个哥们儿出来来到你了,进去完事儿搞定,当然如果说如,这哥们儿呢他是快男啊,非常的快,好,进去之后呢,外面等了一圈儿啊。
俩人就俩人不多,这边呢一秒完事儿,这边发现完事儿了,转两圈就就进去了,ok good,自旋锁,好大家听明白这个问题的就可以了啊。
系列 1:P49:70w年薪面试题:1:一面关于P5的难题是什么? - 马士兵官方号 - BV1mu411r78p
好不废话了,一点点来讲啊,我们嗯用我用最通俗的方式给大家快点讲,其实这里面每一个问题我要讲起来的话呢,都是比较费时力,费时费时间的,但是我用最通俗的方式讲给大家听,大家注意看就行好。
首先我们来解释一下什么叫乐观所好吧,看这里我先给大家解释什么叫乐观锁和悲观锁,我解释这三个概念,自旋锁,悲观锁,乐观锁,自旋锁,听我说,那什么叫悲观锁,悲观锁就是干一件事呢,先往坏处想。
比如说我说一句最简单的,这时候去上厕所,要去马桶上干点事儿,但是只要他一进去,看见马桶空着,当他开始干事的时候,他会会非常悲观的,预计会有人闯进来,能听懂吗,这就是悲观锁的概念,他非常的悲观。
会有人会认为一定有人闯进来,那当然还有另外一种人,另外一种人什么样的,另外一种人是哎,我先坐下,有人闯,进来我再说,有人闯进来,我在做处理,那这种叫乐观的人,你们是悲观的人还是乐观的人,哈哈,都老师了。
我是憋不住的人,好吧,算你狠好听,我说,所以悲观的人会怎么办,悲观的人会进去之后,有人没人都上把锁,能不能听懂,这是悲观的人干的事儿,乐观的人会怎么办,乐观的人是进去之后先干事儿。
如果有人过来之后再把他推走也行,哈哈或者说有如果有人过来啊,排了点出来再给他塞回去也行,就是总而言之,你有人过来之后,我们再做进一步的处理啊,这就是悲观锁,乐观锁的概念非常的简单,那我想问大家一句。
你们平时所接触的synchronized,他这种人我们称他称它为悲观还是乐观的,就如果我写一段话的话,我这样写synchronize,什么什么什么唉,这肯定是悲观嘛,是不是就是你siri这件事来说呢。
就是二话不说,您来了之后呢,上来先上锁,我先锁定,锁定之后才能干事,我不能不锁定的时候是不能干事的,好这种就是悲观锁好,这是被关锁,乐观锁的概念很简单吧,坏事一定会发生,所以先做预防,乐观锁呢。
坏事未必会发生,所以,事后,补偿啊或者适中补偿啊,总而言之呢就是嗯未必会发生自由,我不上锁,先做预防怎么办,上锁,a sorry,先上总,那么这种呢好,我们说一种最常见的乐观锁的具体实现。
它就称之为自旋锁,所以说自旋锁这个概念如果深究的话,它是一种乐观锁的实现,好自编组什么意思,我做最简单的解释,我觉得大家应该应该能听懂,自选锁的概念是说嗯这里举个最简单例子啊,这里这里有一个零。
然后呢我们好多县城都对它进行做加加的操作,那大家知道如果不上锁的话呢,这个零加起来没准儿啊,我加了1万次,没准只能得到个1000多,2000多,这都是有可能的,好听我说。
那么第一种方式是我在加加的操作里前后上锁,synchronize,这种叫悲观锁,还有另外一种方式是我们做一个乐观的处理,乐观处理什么样呢,最简单的方式是说我把这个零读过来做加。
加操作变成一一往回血的时候做一个检查操作,这个检查操作呢被他称被称之为cs操作,叫compare and swap,当然它为什么叫自旋呢,是因为呢如果中间有人改过它了。
那么compared to swap之后呢,读新直过来,这是什么意思,你认真听就行了啊,认真听就行,这是不需要上锁的,就是把这个零拿过来,我把它变成一以往回写的过程之中,如果有其他人已经上完锁了。
已经已经已经把这个值给它加过了,比如说变成八了,同学们,你们你们能够把这个一用用这个108覆盖吗,这个肯定不行,是同学们,这是这,是不行的,那这时候怎么办呢,如果说这个过程之中,你从零已经变成八了。
变成八之后,我把这八再读过来,九再往回写,写的过程之中,如果你这个八又不小心变成100了,我把这100读过来,变成100,一,再往回写,终于有一次往往会写的过程之中,你依然还是100,依然是100。
好那说明我在这次操作的过程之中,没有任何其他人改变过,我在这次操作的过程之中,没有任何其他人进来过,所以我就把你改成101搞定,来这块能get到的,给老师扣个一,那么这块的话呢就不用上锁了。
这种的呢被我们称之为叫自旋锁,那什么叫自旋呢,就是它那个一直循环一直循环循环到有一次成功为止,哎100的过程中,你看啊玩家说100过程中变成101又变了呢,简单呀,比方说变成200了,你就继续来。
什么时候成功一次,什么时候为止,好吧好了,这种人能被我们称之为自旋锁,也叫做cs所,好大家理解这件事之后呢,当然关于自然所面试题比较多呃,关于自检所的第一道面试题是aba问题,是著名的问题啊。
那么第二道面试题就是就是就是现在这种面试官他会追问你啊,你要是深入了解的话呢,这里边东西确实还蛮多的,刚才有同学说了,说这第一道题就得打两小时是有可能的,我快速给你过,因为后面题比较多呃。
第一个问题是aba问题,第二个问题是保障,cs操作的原子性问题啊,那这个问题比较简单,这个问题是一条lock指令,是底层的lock指令汇编级别的好吧,那么a b a问题是什么问题呢。
a b a问题是说唉还是这个零变成一往回写的过程之中呢,发现它依然是零,然后我往回写写,写成一看上去很简单,但是呢这个零啊很有可能是有的线程已经把它改成八了,然后另外一个线程又把它从把改回成零了。
所以它这个零呢虽然看上去还是零,但他中间经历了一个从0~8又到零的过程,好这种呢被我们称之为a b a问题,这个能不能get到,能get到于老师扣一,来就说你看上去还是那个零啊,女朋友例子是吧。
你们非要举那个女朋友例子吗,可以举一个呃,就是这是你的女朋友,这是你的女朋友,然后呢你出差了,等你回来的时候,发现还是你的女朋友,但是这个事情呢中间是不是经历了什么操作,这个就说不说不准了啊。
那这个时候呃当然a a b a a b a问题的解决方案呢就比较多啊,我跟大家简单说一下,a b a问题解决方案其实是有两种啊,就是加其实就是一种嘛,就是加版本呃,从java的时间来看的话呢。
这个jaa版本呢它有有有有这么几,个啊,就是第一个呢是加版本号啊,version,第二个呢是布尔类型啊,就是这两种方式呃,这个如果说不能理解的话呢,你看小例子吧,嗯老师讲的多线程的课,嗯看一眼啊,第一。
就这种啊,这个是那个呃我我们说这是呃呃atomic dereference,这个东西呢是在java里面呢它的一个常用的处理版本号的一种方式,那么在这个版本号里面呢,呃一般来说做任何的操作的时候。
你都有一个sequence,就是你你可以简单理解为你走的时候,给你女朋友脑袋上的写了个一好吧,然后呢如果经历一点什么事情之后呢,这个值就要加加啊,等你回等你出差回来之后。
你发现这里变成了9900 9999,那就说明中间经历了好多好多事情啊,这个大家能不能听懂啊,这能get到的老师可以好吧,这就是使用版本号的方式来解决哈,好那么除了版本号的方式之外呢。
实际上还有另外一种这种呢叫markable markable reference,那么这种方式呢其实它采用的方式是说用一个布尔类型啊,true和false来解释,比如说那么呃这是你的男朋友。
然后呢你你你你你出差之前你啊他脑袋上写了一个写了一个false,好,等你出差回来之后,他脑袋这个false变成true了,那就说明经历了一些事情好吧,当然这个就记记录不了次数了,就是你不在乎次数的话。
你用markable,你如果在乎次数的话呢。
用version好了,这块能get到的老师可以,那如果他版本版本号不对,会干什么,这个就看你自己处理了,你发现他版本号不对,那怎么办,说明中间有人改过,那你要不要检查一下,读一下日志,或者做一下回滚啊。
或者把它踹一边去,这个是你自己处理的事情,ok这是a b a问题啊,当然下面这个问题比较复杂,我在这儿就不想展开了,这个问题的话需要跟到呃,我们汇编指令里面去啊,我在这就不展开了好吧,离婚。
这是你的男朋友女朋友啊,她她并不这个男朋友女朋友并不是单例模式诶,他不是单利,人家可以有多利的,ok啊,single at the,mitan,好这三个概念可以应该清楚了,就悲观所乐观所自旋锁啊。
好我们再来再来继续看,好不好,我们再来看一个啊,再来看一个呢,这个这个东西叫什么呢,叫读写锁啊,排他锁,共享所好读写锁排他所共享所有同学说了,老师这个东西难道还能够这几个概念是是是类似的吗,有点类似。
听我说就行了啊,第一种叫排他锁,排它锁的概念非常的简单,只有一个县城,能访问代码,这是什么意思,最简单的理解,你到一个坑里去之后,只有你一个人,不会有更多的人进来啊,除非那种非常特殊的坑。
这里有面对面的,还有这种麻将似的哈,一边一个坑,这边一个坑,这边一个坑,这边有坑,这边坑中间一桌了啊,当然还有还有这种的啊,这个都可以好不好,但是如果里边只有一个坑的那种呢,啊,特被称之为叫排他所。
只有你一个人能进好,那如果这种人呢这种的啊,你把它看成一个完整的一个坑的概念,这种就可以称之为叫共享锁嗯,还有,上下坑了算你狠啊,有上下铺共享锁哈,共享所知是什么意思啊。
共享所的意思就是说可以允许有多个线程啊,装代码,好了,这是排查所,是共享锁,很简单吧,那synchronize是排他锁吗,来你说说看我刚我刚我刚刚才那个小伙子4834问了个问题啊。
说sychronize是排查所吗,大哥你synchronized的锁定的这段代码是不是只有一个线程能访问,访问完了之后,其他线程才能继续访问,这必须是排查锁好吧,当然有同学可能会问。
那什么东西是共享所呢,我跟你说java里面的共享锁呢,呃它默认的啊,它常见的有这两种,那么第一种是什么呢,第一种我们称之为叫sam for,叫信号量呃,信号量就是你你在这里面呢,你可以。
有两个线程进来permits啊,一共有两个,当然你可以写啊,二二百个也可以随你呃,还有一种啊,还有一种比较常见的呢实际上叫读写锁,我觉得这个读写锁呢实际上是要比sumer比信号量呢更加能说明问题。
所以这里呢我举了一个读写锁的概念,那读写锁是什么意思呢,读写锁的意思呢就是这把锁里面实际上它是一个锁的管理器,它管理着两种锁,就是这个读写锁里面有两种锁,一种叫毒索。
读所的意思是说当我一个人在里面读的时候,不允许写,但是允许,同时读,那写写锁的解锁的时候是写的时候不允许写,不允许,写也不允许,那么你你你读一下这两句话,这个读锁是一个什么锁呀,是不是共享锁呀。
就是允许其他人同时读吗,那解锁呢,解锁就是一个排他锁,这个怎么理解啊,我们举个小小的例子,他的名字叫那一天,你要很幸福好,新闻讲多久,错过了吗啊有一个人叫白虎吧,白虎进坑了,呼哧呼哧排了很多东西。
然后呢白虎呢就就就就就暂停了,这个是白虎是什么,他是写是吧,往里头写了很多很多数据好,当它暂停了之后呢,当他让出这个锁之后呢,围观好,这些人都是读读,有多少人在围观都没关,都都没有任何关系,听懂了吗。
好那那就那个那个那个白虎又要往里写了呢,其他人就不许围观了啊,等我写完你再围观,因为你如果说在我写的时候,你围观的话,你很可能会看到,读解锁的概念,能不能听清楚排查锁和悲观锁的区别是什么,没有什么区别。
排查所围观所区别就是概念上的分配不同,比如说圆的事物和方的事物,这两类事物两两种叫法嘛,好鸡蛋圆的是吧,砖头方的那能吃的和不能吃的也是鸡蛋和砖头的分别,它只不过是分类方法上的不同。
脏读不是数据库里面才有的概念吗,哎哟我的大哥,脏读是任何的中间状态,只要被别人读到就可以叫脏读灵活一点啊,同学们千万别把概念给学死了,脏读本身的概念叫做我读到了别人不允许我读的中间状态能不能听懂。
就是说我一定要穿,把衣服穿好了才能见人,在我穿衣服的,整个过程之中我是不见人的,那么我的衣服穿了一半,如果出来见人,读到了我的中间状态,有一个数字,我要对它加八次,我才能允许他往外见人。
我加了四次的时候被别人读到了,不好意思,好p5 的不太难吧,应该好多人叫统一所分段锁,其实这个统一锁这个概念呢,刚才有同学问说什么叫统一所分段所,统一所这个概念呢,就是不分多少所啊,这个可以叫统一所。
可以叫大化的锁,统一所一般解决什么问题呢,一般就会解决,有大力度的大力度,分段锁呢可以叫分成一段一段的小力度锁啊,小,什么叫统一所分段,这是什么意思啊,就是那个那个一个大锁,一个小锁的意思。
大颗粒和小颗粒的意思,有同学可能会说,老师这个这还有什么大的小的区分吗,这有区分,听我说,我给你举个最简单的例子啊,比如说如果锁定a等待b我有我有一个线程锁定a,等待b还有一个呢叫锁。
还有另外一个线程呢叫锁定b,等待,等待a同学们,你们想一下啊,如果说这两个线程如果同步做的不好的话,会产生什么效果,死锁能不能理解,是不是死锁就会死锁了啊,呃那那呃我们想解决这个思索的问题。
有一种常见的解决方案是什么,是什么,是什么样子,常见的解决方案是什么样子,把a和b统一起来,做成一把大锁,就完美的解决了死锁的问题,ok这种就叫统一所或者叫大颗粒的锁,大力度锁嗯。
他一般是用来解决那个死锁的问题,当然这东西分事儿啊,就是有的时候统一所能力度太大了啊,你比如说给你举个最简单的例子啊,我那个往数据库里插一个插一条记录,我把整个库全部锁定,力度是不是太大了。
那这时候你还要拆分呢,你可以到行几所是吧,可以到表自己所户籍所,这个就看你需要做什么样的一个具体的业务了,如果我我再给你举个例子啊,如果现在我们有两张两张表,我们举两张表的例子吧,我锁定这张表。
我要等待另外一张表的锁,假如说但这种操作很少啊,一般来说是数据库事务的话,呃,数据库内部的锁的话呢,我们就整个锁定我们整个的那个那个那个一个数据库事务就搞定了啊。
然后呢另外一个操作很可能是锁定这边等待列表,那这个东西会就会造成思索,那怎么办呀,好了朋友们,这个叫统一锁,那什么叫分段索呢,就是分成一段段小粒度锁,这个最常见的代码是什么。
听我说是jdk一点七的concurrent hashmap,这叫凉了啊,concurrent hashmap,这个这个是用来干什么的,是什么意思,我给你举个最简单的例子就行了,同学们,你们想一下。
如果说我有一个我们说我们说数据结构吧,我有我我有一个我们说链表吧,链表的例子最容易举清楚啊,好我们这有一个特别长的链表啊,几万个数据,几10万个数据,甚至上亿个数据,这样一个链表。
那假如说多线程对这个链表进行访问的时候,比方说往里头插入数据,多线程进行访问的时候,多线程往往往里插入数据,是不是我每插一个数据就要锁定整个列表啊,锁定整个链表能听懂,那我如果想提高效率的话。
我可以把链表分成一段一段的,我只锁定这一段,我并不锁定整体的,那么其他的段也能同时进行插入,这种就被我被咱们称之为叫分段锁好了,这个p5 的题我就解释完了,看大家伙是不是理解了。
好可以继续,同学老师扣个一,有问题你直接提好不好,上班,有没有测试用数据库表数据库,百万数据库,用测试机构语句嗯,你自己做实验不就行了吗,有代码示例吗,我刚才给你不得看,给你看了,看了好多好多代码吗。
电器所监狱所主要解决的是这个mysql的一个,呃是mysql mysql关于事物这方面的提升效率的一个问题,交易所解决幻读的问题,对这个跟咱们jdk的还稍有区别啊,好了奸细所嗯,屁股多少年薪是吧。
好建议组先你留一下啊,天系数a组稍微复杂一点点,它主要涉及到那个,数据库的行级锁和那个几行级别的这样一种锁,我得稍微准备一下,回头我再讲给你们听啊,三分所一边一般在。
sam ford所一般在什么情况下使用,呃,比如说我给你举个例子,假如你要模拟一个这样的一个状态,这是好多车,然后呢进入到我们的收费站,我们收费站有两个口开放,那你可以用允许两个线程同时运行吗。
不就是就是我们常见的那种什么排队啊,卖票啊,这些都可以理解为是summer的一个运用,限流yes,嗯,1年多开发经验能变阿里p v p6 吗,够了嗯,好那个刚才小伙说那个p5 多少钱是吧。
p5 的话是这么多钱,p5 的话是大概。
p5 大概的钱数,大概是这样的,20万~40万呃,p5 是20万~40万,一般来说呢他们面向的是应届生,应届啊,也就是说不管你是本科还是研究生,那么本科研究生的区别呢,就是本科的他的年薪稍微低一些。
研究生的年薪稍微高一些,另外呢本科生p6 稍微的慢一些,研究生升升p6 稍微快一些,就是给你安排一个任务啊,告诉你明天下午呢把呃订单处理的这段代码给我敲完好,你把它敲完就可以了,这个是p5 的一个要求。
好吧好,我们可以继续可以继续吗,那13可以算pd 13可以就是多少多少星啊。
你自己你自己定级吗。
系列 1:P5:JVM瞬间涨薪3K的操作:5.ZGC的颜色指针算法为什么可以比G1更好? - 马士兵官方号 - BV1mu411r78p
指针这个指针呢它里面存的是个地址,这个地址a指向这个t,这是最简单的java的语句啊,以及它的内存布局是最简单的,对不对,原来我们所谓的垃圾回收啊,都是在这里头,堆内存里头做各种各样的解决方案。
都是在这里头想办法,cdc采用了另外的思路,cdc是在这个小t上想办法,是在这儿想办法来,所以我们下面要关注的是这个指针本身,这个地址本身来,我刚才讲的这一小段能跟上的,给老师扣一。
ok那这个地址首先第一点,cdc是不支持32位的,所以cdc的指针最少是64位的指针,好吧,大家都知道这个64位的指针呢,最长的寻址空间啊是二的64次方,二的64次方,没有这么大的内存。
用不着这么大的寻址空间,只用其中的这部分就可以了,这部分是42位就够了,那么42位能寻址的空间是多少呢,二的42次方大概是四个t,后来呢cdc又加了两位,一共有44位jdk,13的时候。
大概现在寻址是16个t嗯,现在很少有这个大家见过16个t内存的,机器吗,我是没见过,我见的最多的是1。6t,我记得是1。5t左右吧,你们见过有谁见过16个t内存的机器,有没有有有有有,应该没有啊。
有结果,那就见了鬼了好吧,所以呢我们说指针长度用不了这么多,用44位就可以了,所以后面有一堆呢没有用的那个位位,怎么办呢,就在这里给做出几个标记位来,那么这几个标记位用来干什么。
用来标记我们这个指针的状态,比如说我们这个指针在所有的分区里,最开始的时候是一种状态,当然这种状态呢叫rema,然后呢当我们开始标记,的时候,我们主要解决的不就是并发标记的问题吗。
我们开始标记的时候就给它标成mark 0,m0 ,标成m0 啊,每个对象都给它标成m0 的状态,表示我我标记开始了啊,我标记开始了,然后对于这个m0 的处理,这个过程嗯比较复杂。
我只能说我今天呢就给你简单讲讲,讲原理就完了,好不好,后面我找时间,我专门给大家把这个过程给大家做成动画,你就更容易理解了,就是当我找到这个m0 对象的时候,我只要从根上开始找啊。
我垃圾回收器从根上开始找,我只要找到任何一个对象,我就,把它标成m0 ,好,我再说一遍,稍微的多说一点点,最开始的时候我们有一个对象的状态,整个整个内存里头啊,分了好多区域,首先这是第一点。
分了好多区域,好在这个区里面所有的对象都是一种状态,这种对象的叫remap,它具体是什么意思,我们不管,然后呢,我垃圾回收器十点钟开始找,我从根儿上的对象开始找你女朋友,你男朋友找到一个对象。
我就把它标成m0 ,找到一个对象,我就把它标成m0 ,所以最后就会变成什么呢,我们整个内存空间里都会变成有m0 存在,有remap的存在,凡是m,零就是活着的,凡是remap就是垃圾。
这个不知道大家能不能理解啊,然后比如说它它它在这个指针上,它只动指针,它不动内存能听懂吗,这块就简单多了,当然它中间呢把这个m0 找出来之后,如果我们决定要回收这两块空间,那这个过程也比较复杂。
他需要把这两块空间的对象,给挪到另外的一块空间里面去,那就意味着这个指针这个值是不是得变呀,所以它后面再加一个屏障,就jvm级别的屏障,只要是m0 级别正在挪动的时候,就把这个指针给它变过来。
所有的业务线程访问这个m0 的内容的时,候,就把这个指针的内容给他变过来,好不知道我说清楚没有,大概的啊,16t的硬盘都没见过,这个过程本身比较复杂啊,有m0 m1 ,cdc没有完全听明白了呢。
就先放过他,关系不太大,目前主要是目前的关系不太大,嗯现在是09:50,我从现在开始啊,来给大家讲解一点关于实战的内容,可以吗,来准备好的同学,你们还活着,还能跟上吗,还在吗,老师扣个一啊,这么恐怖。
内存地址都变了,不是杨树啊,这个杨树居然问了个,这么这么这么土的问题,大哥来,各位同学,到目前为止,你们好好思索,我们所讲过的任何的所有的垃圾回收器,有没有一个不用变内存地址的,有没有,琢磨琢磨。
我说的是所有的垃圾回收器,1+7怎么了,看见你了,有没有一个不用变内存地址呢,一个都没有,我告诉你,因为我们说年轻代的,你们想啊,就是年轻代的这个这个这个算法的时候,是需要把对象拷贝的。
对象拷贝什么意思啊,不就是把这个对象的,从这个地方拷贝到了另外一个地儿,那我想问你指向这个对象的指针,你你你你这个值不变吗,不然的话你通过原指针还能找得着吗,所有涉及到复制的地址是一定要变的。
所以这个东西跟恐怖不恐怖,有半毛钱关系吗,都要,变啊,还能跟上吗,好我讲点实战,讲点轻松的啊,理论的内容啊,确实它非常的复杂,告诉你嗯。
讲点稍微轻松的,讲点实战实战就是就就轻松多了呃。
教大家一点。
小小的实战的内容啊。
呃首先教大家第一个命令就是java conversion,我同学说这个不用交,这个都会是吧,呃大家听我说,这是检查java到底属于那个版本呃,同时呢直接就敲诈吧,什么都不敲回车。
你会看到这是jvm的所有的参数,凡是以横杠开头的参数。
这些都要标准参数,我们所谓的jvm调优。
我们调的什么东西呢,参数的值就这个意思。
凡是以横杠开头的,全部都是叫做标准参数,这里面呢我们应该也有的人是用过不少的,比如杠version,我刚才给你用了对吧。
指定class path路径等等,呃当然还有同学可能如果听我讲课,有可能用用过这个叫杠java是吧。
这是那个java编程接口啊,呃当然还有其他各种各样的杠,第323 12位的杠,第646 14位的呃,server server模式。
client client模式是吧,这都比较简单呃,有同学可能会说,我我我我去了解这种参数的时候,也太简单了。
就这么二三十个,我想调的时候非非常容易调啊,呃没那么简单,因为真正调参数的时候呢,往往有第二种参数,那么这种参数呢叫做nonstandard options。
print help on nonstandard options。
以杠s开头来瞅一眼clear。
这样的杠x回车好,那我们回车之后呢。
我们会看到以杠x开头的参数,这些参数。
那么我估计有同学应该会用过这个杠,xm堆内存的最小大小啊,你可以设我这个java程序要用多少内存,最小用多少杠x m x,最大有多少杠x s s是吧,这个是占的大小。
哎咱们小姐姐有人带吗,跟同学们聊会小天,我得喝点水,嗓子快疼死了啊,大家稍微等我一下,我我我喝点水,上个上个上个厕所好不好。
老师用的什么环境,win还是mac诶,我想问你,jvm在生产环境里头,一般运行在什么环境上,对呀,老师用的当然是linux了,我在win下面给你演示,没有意义的,听懂了吗,我在mac下面给你演示。
稍微有点意义,因为它叫做类类类unix系统啊,ok让我们九妹跟大家聊一小会儿啊。
我上省会。
ok我我我我们继续上课,呃vip课呢肯定讲的比这个要细致的多,呃,比方说每个参数什么意思都会讲给大家听,呃同时呢也跟大家说一声,今晚呃如果对课程有兴趣的,呃我们今天晚上的报名的话呢,也是双11的优惠。
那么1年之中呢最大的一次优惠了,双11呢我们今晚报名的呢,也是有那个抽奖的权利,然后的话呢报的越早的话,抽奖的概率就越高啊,就是这么设计的,ok嗯刚才呢我讲到说呃,我们进行一个jvm调优的时候啊。
没有两种参数啊,第一种呢是横杠开头的,那么这种呢是标准,参数第二种呢叫非比非标参数啊,杠x开头呃,其实我们读一下的话也就几十个,看上去也没那么复杂,但是呢实际上这里头是没有显示出来的,是另外一种呃。
另外一种参数就是以两个x开头的,是这种的java杠x这个开头的,那么这个参数呢,不知道大家同同学有没有用过呃,有用过的同学老师扣个一来有没有,有有吗,嗯不对啊,呃哼呃,戴尔好像加我微信了,还是吧。
ok笑傲江湖,ok gus开头的这个参数到底有多少呢,呃由于它没有显示出来,所以我们必须用一个命令来告诉大家,这个参数到底有多少,我们这个命令是什么呢,有两个命令啊,用其中一个就行了,print。
flex final,那这句话的意思是说,我们把java虚拟机的所有的flag,就是所有的参数,它最终的那个值全给你打印出来,由于这个数值特别多,所以我让他分个页,加一个more。
回车好,这是第一瓶从a开头的参数。
b开头的,这里我们会看到我以前讲过的偏向锁c。
ok这个到到底有多少呢。
wc杠没事嗯。
恭喜你,一共有728行啊,大概有700个参数左右吧,扣了扣了这些个。
大家都在那干嘛呢,在跟着克总吗,出来了是吧,来你们你们试过了是吧,哈哈哈,呃你的这个mv需要调优的话,大概有700个参数左右,所以当我们看到。
ppt里面,这句话的时候,来同学们看一眼,你说当我们把这句话写在我们简历上的时,候,我们是不是得多值个两三千块钱呀,熟悉常见的蓝鲸回收器,具有实际gm调优的实战经验,是不是得多值个2000块钱啊。
没问题吧,当然我们话说回来啊,这个呃如果700个参数你都需要了解,都需要调的话,这个难度也太高了是吧,没关系,老师给你记录得非常的清楚啊,我告诉你呃,大概常用的就这么几十个,我呢已经给你记录下来了。
最常用的就这么多,不需要记其他的好吧,我们ps加po常用的就这么多,所以ps加po的话,其实配合上上面参数没多少,但是cms本身比较多,而且比较复杂,所以cms一般我们不太建议用g one的。
常用参数的话呢,其实就少了很多,而且相对比较简单,关于z dc的话呢,基本上就三个参数,所以呃,这个呢就就就呃我我给你总结下来呢,大概有四五十个吧,四五十个参数,而且呢不同的垃圾回收计算下来的话呢。
20个左右就够了,是不是感觉世界又美好了一些,来有信心往这上面写这句话的同学,给老师扣个一,调调坏了,到了重装就是了,说的很对,就是你要大胆,当你把这个这句话写上去的时候,必须把该学的东西都给我学了。
要不然的话人家面试官可能会怼你啊,当然呢呃从实战的角度讲呢,其实有一个很重要的内容,就是日志这方面我没有讲,日志的格式本身也很重要,呃时间关系呢我就讲不完这个了,我给大家讲一个调优这件事情。
最常见的就是我们去找出来,是有哪些对象产生了o o m,这个呢在你简历上写调优的时候,是最容易cover得住的,而且呃讲的时候呢,你也能够讲得比较到位的啊,o o m那么关于o本身啊,内存溢出。
关于内存溢出本身呢,这个呃比较简单的方式是什么,你们你们自己能写一个,那让它内存产生溢出的程序吗,如果是你们要自己写的话,你们自己写一个最简单的,让内存溢出的程序怎么写,死循环死循环。
你能你能写得出来吗,猫那不可能啊,死锁死锁,你跟那个内存溢出没有半毛钱关系的,无限递归叫做战役出,它不叫堆一出,不叫out of memory,它叫做stack overflow,大哥,我要出括号。
你要这样能内存一出来,我就佩服你,你试试去,设一个固定的内存,一直new对象,疯狂扭list里面放list,对各位同学,你们实际写写,你们未必能把内存给弄崩了,我告诉你不是也不是那么容易的。
当然最简单的方式是什么,你你要搞一个list的,首先这是在你的main方法里面搞个list,我们看给大家写的最简单的案例吧,日志就略过不讲了啊,嗯这个案例,呃这张里面最简单的案例是是什么呢。
就是你弄你搞个list list list等于new一个link list,然后呢不停的往里头list里面加啊,这块很重要啊。
我觉得有同学可能不知道在哪,存在着一些误解。
系列 1:P50:70w年薪面试题:2:二面关于P6的难题是什么? - 马士兵官方号 - BV1mu411r78p
我们可以聊p6 的内容了吗,可以的话,老师扣个一好吧,阿里没有13k,阿里好像是没有13k的。
不记得有13k,我们来聊这个线程池的理解和运用。
首先我先问大家一句啊,呃有没有同学不理解什么叫线程池的,这需要我解释吗,需要我解释的,老师扣个六线程池这件事应该不需要啊,不理解是吗,有这么多不理解的吗,一直半解哦,好好好好好。
我知道了好停吧停吧停吧停吧停吧,停下来停下来,关于线程池这件事情呢其实非常的简单,同学们,你们想要我给你举个简单的例子啊,呃现成的费用对说的很对,比如说啊这是一个餐厅,那么作为餐厅来说呢。
你你你进来之后呢,你是要找座位去吃饭,呃每一个线程可以理解为我们一个后台的服务员啊,我们餐厅的服务员,同学们,你们想一下,如果有一个人过来的话啊,那最容易的一个一个方式是什么呢,我给它起一个线程。
也就是有一个服务员来为这个人服务,有一个服务员来为这个人服务,那如果有1万个客人进来,那我就需要有1万个线程来对它进行服务,而且呢每一次都要new这个线程出来,就是把这个服务员给new出来。
这效率实际上是比较低的,那有没有另外一种方式呢,这种方式就是说我现在呢有20个服务员儿,但是呢我一次性的把它弄出来,一次性把它雇佣进来,放到哪儿呢,放到一个比方说数组里面。
列表里面唉这个都可以随便就总而言之呢把这些服务员全丢出来,也就是说二话不说,先new 20个线程出来,把这个thread全部给new出来,用完之后放到哪里去,放到一个水结构里面去,数组链表完成。
所以所以你放进去啊,然后有一个哥们儿过来之后,派一个人出去给他服务,完了之后再回来,下一个哥们来的时候,这个人这个县城还闲着呢,因为他已经处理完第一个第一个哥们儿的事儿了,好再给他服务区。
第二个区第二个服务,然后再回来,那这样的时候我就不用每次都new线程县城的重复使用,这个东西被称之为叫县城池。
来线程池的最基本的概念能听懂的,老师可以没问题吧,嗯这算是用内存换时间吗,啊你是有这么点意思,你说的很对,嗯,简简单单的啊,这里面其实不能说电影的那复杂的事儿比较多,呃我们讲讲真正讲vip的话呢。
实际上不是要分析到这个线程池的源码级别,它这个呢就相当于你要到p6 plus啊,接近p7 就拿比较高的薪水啊,需要的111个内容,嗯从老师这儿来讲呢,我一般不建议大家就是在你刚开始的时候。
你就去研究源码级别的内容好吧,先去研究它怎么用的,这东西有什么有,什么有什么用,有什么意思啊,所以你第一步呢先去了解什么呢,就是关于线程池这件事情啊,我构建一个自己的线程池,构建一个z的线程池。
它到底是怎么构建出来的,每个参数到底什么意思,这个东西呢是面试经常会被问到的,就是线程池的七大参数呃,七个参数呢也不太容易完完全全的理解,但是我建议你呢你就给他背过就完事了好吧,应付面试也行好。
这七个参数是什么意思呢,一共有七个参数,大家注意看就行了啊,我我记得我画过一张图,我用一张图呢差不多给大家。
把这个七个参数呢都给大家列出来吧,找一下,这样读啊,看看这里啊,这个线程池一共有七大参数讲给你听,我们先过一遍,简单过一遍,现成吃鸡大参数哪七大参数好,第一个参数呢叫做core process呃。
核心线程数,核心核心池的大小,核心池大小,第二个呢叫maximum process,叫做最大值大小呃,叫生存时间,第四个呢叫生存时间的那个单位嗯,第五个呢叫这个是非常著名的一个这个东西呢叫做任务队列呃。
第六个呢叫做线程池产生的工厂,第七个呢叫拒绝策略,我一点一点讲给你听。
你认真听,这个不难回想一下啊,第一个参数叫什么,第一个参数叫,第一层叫什么,叫核心池大小是吧嗯核心应该叫核心线程数量吧,核心线程数好,最大线程数好,第三个加第四个,这应该叫3+4吧,叫做那个生存时间。
时间单位,这里面比较麻烦的是第五个。
第六个是什么呢,呃第六个是。
县城工厂好,第七个是什么呃,第七个是拒绝策略,ok这是七个参数。
我给大家先做简单解释,你注意看什么叫核心线程数,核心线程数的概念啊,就是你的池子刚开始的时候,你不是一堆服务员吗,你刚开始的时候雇佣了多少个服务员啊,我平时我这餐馆啊有俩服务员够使了。
只有人多的时候才忙不过来,所以呢我核心的服务员就有俩啊,这个被我们称之为核心线程数,就这俩叫corpus size呃,那这时候如果来来客人了啊,来自来客人要做任务了是吧,嗯t呢被我们称之为叫一个任务。
一个rable啊,一个task呃,一个任务要扔进来了,他要点餐啊,要过来了,来来来为我服务啊,捏捏脚,点,点个餐好,这时候我们首先呢肯定是交给我们的核心的,这样的一个一个服务员去去做。
但如果是俩服务员都被占住了,都被占用了怎么办,听我说,这个时候有一个东西呢叫任务队列啊,就是它叫work you,叫任务队列,任务队列指的就是你排队把你放到哪儿去,排队门口排队去,我核心数满了。
你就得门口排队去,所以如果这时候任务再来,他去哪了,去排队去,那我排我队伍排满了,比如说我排队的这个队列最大的数量就允许四个四个人在这排着队,我,就四把椅子在门口排队,那这时候怎么办,又排满了怎么办。
没关系,所以这两个一加就叫做最大线程数,好这两个这两个概念是不是听懂了,非常的简单吧,我一餐馆就俩服务员,有俩哥们儿过来把我俩服务员全站住了,怎么办,来排队去排队,排满了怎么办,又来人了,又来人了。
这七八过来直接插队,对这七八过来直接插队,是这样的嗯,当然这东西我我直接告诉你啊,就是直接插队,不直接插队呢,实际上是取决于你线程池的具体实现,那好那同学们,你们想一下,这两个人干完活了之后。
他会他会怎么做,注意他会从任务队列里把这些人,把这些排队的人拿过来继续运行啊,t5 t6 哎,这哥这哥俩呢干完了,他把t3 t4 拿过来,能不能听懂,那这时候呢我们忙完了。
等于是啊我们等于是任务队列也没人,也没人了,好在这种情况下,在这种情况下,如果这哥俩的等待时间超过什么呢,超过第三个参数和第四个参数的组合,比如说我们第三个参数定义的生存时间是60,时间单位是秒。
当然也可以定小时啊,随你也可以定天,那随你变时间单位是秒,这哥俩消失干掉,但是核心的线程永远存在,来这前面这四个参数能听懂的,给老师扣,一是很简单,我给你讲就比较简单啊,我不跟你讲。
你要自己读就稍微麻烦点,是的。
好在这就不演示了,这样的演示其实也非常简单。
你只要定好任务,给每个任务做一个编号,然后呢定好你的cos以及maximum maximusize。
定好之后呢,再来呃详细的去运行,你观察它的特点就可以了,知道吧,这非常的简单啊,不能嗯,好了,队列长度是怎么设置的,问得很好听,我说这里面一个难点呢是这个队列的选择,注意怎么样排队,这个队列怎么选。
这是一个难点,也是一个重点,但这个东西要展开的话呢,内容就比较多了,这个队列呢第一你可以自己定义,你可以用数组,也可以用列表,第二呢你可以用现成的java里面的容器,只要是和q这个接口相关的。
q接这个接口,队列这个接口呃,这个继承下来的好吧,实现了它的你都可以用,这里面东西比较多,我在这就不展开了,就没法展开,是这十几个十几种的啊,比如说你可以用什么用concur map,如果你要愿意的话。
你也可以用copy on write list,就是呃写实复制呃,也也可以用什么concurrent q,也可以用lb q l bq就是link link blocking cu,也可以用什么呢。
a a blocking cute,也可以用什么自带那种优先级的,你懂不懂,就是嗯堆priority q自带优先级的,就是那个优先级高的往上排,优先级低的往下来,delay you。
这个往后延迟多长时间的,还可以用那种容容容容量为零的叫synonk,那就必须得我这边必须得拿走了之后,我这个生产者才能走,还有一种是什么transfer cute,这个是容量为零的啊,这是现成的,别人。
已经提供给你了,那在这个基础之上,你也可以自己去实现,你想用什么样的就用什么样随你,比如说你做一个那种q里面说这个这个编号为单数的,你你就你就扔进去,编号为双数,你给它给它,给它在这个分叉上。
或者给它给它去掉,还有还有一种比较牛逼的q是什么呢,就是这个环形的队列啊,比方说disrupter所使用的那种,所以这是一个难点,但是你记住这个东西是一个容器就可以了,在这儿刚入门的时候。
你把它记作一个容器就ok,好哇这个l o p问了一个触及灵魂的问题啊,你这个问题确确实实很很多的那个面试官会问啊,说核心线程数最大线程是怎么设,这个事儿呢,是一个一般来说,一般来说你得估计你并发量嘛。
就相当于你核心线程说的话,你要对得起你最低的这种并发量啊,你比方说日常的情况下,我这个并发100个人,那我这时候我要算一下他时间是多少,等待时间是多少,计算时间是多少。
然后呢给他算我有多少个服务员能服务过来,但是我高峰的时候呢,我很可能达到1万个人,我要请多少个临,时工我要把这个射到多长啊,要做压测,当然当然听我说嗯,这种东西的话呢,它比较复杂。
我呢在这儿给你简单给你给你聊两句啊,你认真听,只有这个事儿,只有认真听才能听得懂,认真听,假如说我们想提高整个程序的效率,什么叫提高整个程序效率啊,什么叫提高效率啊,我们能把我们的cpu占满。
能不能听懂,占满占到百分百,我现在假设我们只有一颗cpu好,我现在有一个任务,这个任务他百分百的时间都在使用,cpu是一个纯计算的任务,我想问你,我们设多少个线程,设多少个线程能充分,利用cpu跟我说。
哎呀你们都是一知半解的,别搁那儿,别搁那儿,往往往往外瞎说观点了,全都不对,我说的说一说一的都是对的啊,就说你一个一个线程数来了,就把这个cpu给占了,那这个一是对的,那假如我问你,我问你。
如果这个线程它用作运算的时候只有50%,另外的50%是io的等待时间,那我告诉你,我问你用多少个线程能让cpu占满百分百,这个时候就是两个,那如果说它的计算任务只有20%,我们设多少个线程合适。
这个时候就是五个,这块大家能理解吗,所以你设多少的线程,是跟你的任务到底是io密集还是cpu密集息息相关的,来这块能get到的,老师可以,所以不要跟那瞎说说什么二乘以几的倍数胡扯,那属于啊。
有界队列和无界队列该怎么选择啊,这里头有同学们对那个线程比较了解的呃,首首先说什么叫有界队列,什么叫无界队列啊,听我说有界队列的话呢,指的是我这个队列呢是数量有限的啊,比方说它就能装五个好了。
这是数量有限,无界队列指的什么,最常见的是链表,我这反正只要在屁股后头加就可以了,它长度多少无所谓,听我说永远使用有界队列,不要使用无界队列,嗯这个事儿呢。
这样我给你们要不要要要不给你打开阿阿里的那个那个编程规范,阿里的编程规范,编程规约,你们你们有吗,自己读过吗,自己读过吗,没有是吧,应该有吧,呃你这临时要我给你找一下啊,我看我看我放在哪儿了,嗯嗯。
不找着看啊,work boos,这这个我这版呢应该是不是很新的一版啊,但是呢呃新的一版呢你们可以去网上搜就搜了啊。
这是阿里的那个叫华山版,新的是新的,是哪一版,新的叫泰山版,还是叫什么。
就是关于并发这块啊,关于并发的处理。
就并发处理的话呢,这是关于线程池的一个它的一些规约呃。
我建议你们有空的话去读一读这些规约,想想看这是为什么好不好。
看这里看这个呢县城是不允许用executed去创建,而是要用three two execute方式支持,就是我给你刚才给你看到的源码,就是使用这种方式。
你得是手工来取,这个原因是什么呢,原因是呢呃executors它默认的一些东西啊,比如说fixed和single threpo,他这个默认的队列是多少呢,是max value。
而这个呢catch the po也是max value。
这个数量是超级大的,是什么意思,就是它这个队列呢超级超级的大个儿,这个队列啊,它不能叫无界,它有它也是有界,但是呢它超级超级大,那index max value那是多大一个数字。
也就是说你很有可能你在这里边儿,假如,说我们的呃消费者线程死了,我这县城不动了,而且呢并发量超级的高,双11的这种并发量,很快里边的消息就堆满了,能不能听懂,这就满了堆满,那堆满的话呢。
会把我们的内存全部都给你占,光,是不是出问题太长了啊,所以不要用你说有界和无界,你首先要用有界,而且要用合理的长度啊,当然你可能会说老师我们业务无所谓啊,我就是一个给成员植发的店是吧啊。
200年不来一人是吧,那好那这个时候呢你可以把这个队列设的长长的,反正我总有时间去把他的队列里面的人给消,化掉这个无所谓的事情,所以具体问题具体分析,但是尽量不要使用无界队列,这个太狠了啊。
很有可能一出问题就全全装满了,来这块儿能听明白的,老师可以,呃我们再把打开啊。
既然又讲到这儿了呢,呃我们再来看啊,你看那个其实呢他在这里面呢还有很多很多的呃。
并发处理的一些个规约,那么在并发处理的里头呢,他说创建线程或者线程池的时候,指定有意义的名称,方便出错时回溯,这个是什么意思啊。
同学们认真听呃,你们想一下,这这个是第第六个参数的含义。
这个第六个参数啊指的什么东东呢。
创建县城的工厂,有同学说了,老师大哥这事儿有问题啊,我创建一个县城不就new一个thread不就搞定了吗,是不是啊,搞定了我我我我我搞什么,其他的搞什么其他幺蛾子好听,我说听我说。
其实呢你创建这个现场的时候,我给你举个最简单的例子啊,这个new thread new出来的这个线程的时候,它的名字叫做默认的名字,如果你装在线程池里呢。
它一般叫做叫做pro 1 thread 1 pr thread,二puls pr thread 3,就这里的名字,我想问你,如果当你看到这样一个名字的时候,就好像说,一旦出了异常,exception。
exception,一旦出了一个异常,那你看到这个名字的时候,你会你你能知道它到底是处理哪方面业务的线程出的异常吗,的意义是没有名称的,就好像你变量起了一名叫a a a b b b啊。
变量叫a1 b2 ,这样的变量能不能被允许吗,绝对不可以,尤其是像阿里拉京东了这样的大厂里面,他们一个机器上跑的线程数量可能非常的多,好多人都使用线程池,那这个这个人使用的线程池叫thread一杠一。
另外的人写写写写的限制是,thread 2杠一,你说这俩出了bug之后,出了之后到底是哪个业务组产生的,这块能不能理解,所以呢在这个里面实际上你可以手工指定一个自己产生现成的工厂。
但自己选择下面的工厂的话,你就自己起名字就好了,比方说我现在处理的是凉菜业务,那可以叫凉菜,凉菜张三儿啊,凉菜李四儿啊,出了问题之后,你能找着人好,这块能理解的,给老师扣一了,只有我的线程池才敢这么写。
ok你牛逼,好了同学们,我讲到这儿呢,其实1234566个参数我基本都给你解释过了,细节呢还会比较多,尤其是像中呃任务队列啊,在这儿就没法展开了,好呃那我们说我们说下一个啊,下场只能用用英文名。
用中文也会报错,那我也很少用中文,关键你用英文名就用英文名吗,这有什么关系吗,完全可以用英文呀,就总而言之,你就是把它起个有意义的名称就可以了,好吧好,我们看这里啊,我们最后一个参数。
最后一个参数呢实际上把我们把它称之为叫拒绝策略,拒绝策略是什么意思呢,就是你再牛叉的餐馆,你服务的能力再强,也隔不住n多的流量一块涌进来啊,海底捞啊,够牛叉了,对不对,这个像什么喜茶啊这一类的。
像什么胖哥俩等等,这个服务能力已经很强了,但是,你同时能够服务的人也是有限的,好了,同学们,这时候你就琢磨了,如果在我们同时服务的人全满了的时候,又来新人了,我该怎么处理。
大概就这个意思啊,看这里我们的任务队列也满了,我们的备用服务员也用完了,好这时候又来一个,这时候怎么处理这个赶走慌了,直接我滚蛋,下次不许再来了是吧,可以是个办法嗯,这是店大了欺客,刻到了气垫。
存起来持久化可以说的很对,比方说有一些我们不能够丢掉的消息,当他要来的时候,同学们,你们琢磨琢磨,我们能不能够把它丢掉吗,这个不可以啊,这时候怎么办呢,先把它持久化起来,把直角画起来啊。
当然这里面的策略呢非常的多,默认的策略有四个,默认的我说的是那个jdk自己自己帮你实现了,有四个啊,但是不展开了,但是还有,但他这四个呢其实实际当中用的并不多,我告诉你一个最常用的啊。
就是你在这个服务外面呢可以搭一个mq的集群,卡夫卡rocky mq都可以当这个任务来的,时候实在没地儿处理了,先扔到mq里再说,就是你你有一个持久化它的地方,刚才说了,持久化说的很对。
什么时候我这边空了好,从持久化的队列里面再拿出来再用呃,这块大家能听懂吗,那都有同学可能会说了,流量太大了,直接把这个持久化就给灌满了,怎么办,动态的弹性扩缩容,能够把它给扩容,说还不行怎么办,还不行。
就限流,再不求你熔断是吧,好这第七个参数啊,现在我们回顾一下这七个参数,看大家是不是理解了,嗯,好看这里,呃第一个叫核心线程数啊,我们核心呢你在脑子里想,我们核心俩服务员哎,最大线程数最多。
我们来四个服务员是吧。
唉然后呢生存时间说那个临时的服务员多长时间,你不理它,它就自动的死掉了,那任务队列你得有一个排队的地方。
那个排队的地方呢由于是多线程要对它进行访问,所以呢要做好同步,就是各种各样的同步队列,然后呢县城工厂啊,你需要指定一个有意义的名字,或者把这个建成呢指定成为后台类型啊,那第七个呢拒绝策略常见的有四个。
这四个呢第一种是扔掉,第二种是什么套异常啊,第三种是那谁谁谁调用的,谁用啊,第四个呢再起一个新的等等,但是呢这种不太用,实际当中用的不太多,一般来说我们不会扔掉它,这时候我们不会扔掉它,怎么办呢。
做日志扔到m q里就可以了,ok来能够现在有信心能够把p6 的题答出来的同学给老师扣一来,几点了,9。10分啊,正好正好我们讲p7 好不好,0。5是吧,嗯可以可以可以,好嘞好嘞好嘞好。
系列 1:P51:70w年薪面试题:3:三面关于P7的难题是什么? - 马士兵官方号 - BV1mu411r78p
好,到现在为止呢,我基本上粗浅的啊,为什么说是粗浅的,就是里面好多细节呢,我并没有完全展开,粗浅的给大家交代了,最近所面试到的p5 p6 p7 p8 的p5 p6 p7 的内容,这是关于线程方面的。
当然p5 p6 p7 的内容也会比较多的,不是说只有线程方面,我只是挑了县城这方面给大家讲而已,乐观锁,悲观锁,自旋锁,螺旋锁,排查锁,共享锁,通行所分段锁,这当你在看到这些概念的时候。
一定脑子里先把这个东西给他浮现出来好,那么第二个呢是关于线程池这方面的,这个就别说,了这个现关于线程池呢,这是问的,问的非常非常非常多的,你啥也别说,就给他背过就行了,线程池的七个参数啊。
核心线程想想看啊,最核心的那个服务员,最大线程最多有多少个服务员是吧,任务队列排门口排队,那哥们儿啊,那个那个那个那个队列,现在的工厂给每个县城起的时候呢,起一个自己特殊的名字,拒绝策略四种比较常见的。
但是很少用啊,也可以自定义地拒绝策略啊,呃当你理解了这件事之后呢,关于pg来说呢,我给大,家分析了什么叫线线程,它的另外一个名字叫携程,它有普通的债务线,就是不同,为什么能提高效率。
因为它节省了切换的时间,好了嗯,我在这儿给大家追问一个小问题,追问一个这样的小问题啊,是不是兼程,永远b就是可以这么说,是不是m bn模型永远优于,一比一模型啊,这我直接说答案啊,这肯定不是啊。
同学们听我说,如果你的线程数量其实等的挺多的,就等待情况特别多,嗯对不是没错,不是,你看到永远这个词儿它就肯定不对,是不是同学们,同学们听我说,同学们你们思考一下,我们说m bn模型有一个什么毛病呢。
就是它永远是消耗cpu的,能听懂这个站在操作系统的角度,这些这些个线程没有人是没有人是进入睡眠状态,或者没有人是进入等待状态的,就这些个玩意儿啊,他一定全是活着的,永远是消耗cpu的。
但是如果我们使用的是一比一模型的话,那么这些线程我是可以控制它进入等待状态的,weight它是可以释放cpu的,所以当我们有一些操作,比方说这些操作呢它的耗时非常的长,它的并发量也比较大,那这种情况下。
一比一模型实际上有可能要优于ba模型的,因为只有一个线程在工作就可以了,或者只有几个线程工作就可以了,其他线程进入等待队列,不要给我消耗cpu,来这块能听懂的,给老师扣一,当然要透彻理解这个先生的话。
阿里内部的县城是自己呃,他们是完全用过的,好吧,阿里内部的先生他们是完全用过的,但是呢呃平时可能大家伙用的少啊,不过老师这个课呢就是追求的比较全啊。
各方面的内容都都都都比较全,比较比较完整呃。
所以呢基本只能只要你能想到的啊,老师这课里头基本全都有,那我讲完p5 p5 p6 p7 ,你们想知道p5 p6 p7 拿多少钱吗,想知道的给老师扣个一好吧,好,哦sorry啊。
就就这个课啊,对不起,我这课这课名字叫携程啊。
这个叫那个高并发解决方案,只写成了,对不起,我说怎么没搜到呢。
他是那个呃是是携程啊。
名字起的叫携程讨厌,所以啊记得是油滴,嗯嗯。
哦在这儿在这门课上嗯。
mc高并发的这携程这个是咱们阿里的一个p7 的老师。
他们在实战之中呃,运用携程来解决这种高并发的问题,我觉得这个案例呢还是挺好的啊,嗯代码的场景啊,代码的解读啊,代码的答疑,io是怎么做的,并发模型是怎么做的啊,回顾一下写成killing到底是怎么做的。
呃讲解昨天的例子,阻塞的理解啊,最后是一个大一呃,当然这是我们整体课程中的一小部分了啊,我们基本上整整个的课呢是p5 p6 p7 p8 全有。
那我看有同学想了解那个p5 p6 p7 p8 到底是什么样的一个要求。
心率是多少呃,在这儿呢你们要想开这个网页的话。
我在这儿写的其实非常的清楚,这是咱们阿里的曹老师把阿里那边完整的一个要求给大家呃。
全部拿过来的,p5 的要求啊,它的年限一般是给到20万~40万。
好吧,p6 的要求是什么,p6 年年薪是40万~60万啊,他的要求是一种独挡一面,在专业领域具备辅导他人的能力,那我问你啊,这个专业领域具备辅导他人,他辅导谁啊,独当一面辅导他人,辅导谁,辅导屁股吗。
对辅导p5 是这样的啊。
然后呢嗯在站在p6 的角度,然后p7 p7 是年薪50万70万,他当然他时他就有股票了,是8001200股呃,这时候它叫做领域专家,一杆到底系统性思考这个东西呢,就是他在p6 的基础之上呢。
它会变成一个领域专家,大家记住,当你看到领域专家这个词的时候,一定要有一个有有一个词儿要出现在你的眼帘里,出现在你的耳耳门里,出现在你的脑子里,这个词叫业务,好听我说当我们成为一个技术架构师。
成为一个技术的高手之后,请你一定要拥抱业务啊,我们说p7 到p8 ,它的一个跨越的点在哪。
就是这俩字儿啥业务啊,好听我说我我简单给你们解释就是什么情况下你会到p5 。
什么情况下你会回到p6 ,什么情况下能到p7 ,好认真听,一般情况下你是应届生,这个应届生呢还得是本科的应届生,然后本科也或者是研究生好,ok这个时候你的直接进你的级别,如果你能练过的话,p5 。
那么在这个基础之上,p6 是什么意思呢,p61 般情况下它和p5 的要求,所以我说p5 p6 p7 啊,实际上不分家,在我们整体课程里头呢,这三个东西呢也叫做一门课啊,就p5 p6 p7 是不分家的。
听我说,一般来说什么情况下你回到p6 呢,p6 是你一个模块的负责人,你把这个模块分解成任务之后,可以让p5 去做,你督促他去完成,就在别人的帮助之下,别人给你下达好任务之后,你能完成。
ok好你这什么叫做p6 呢,一般情况下是本科生毕业1年左右,专科生毕业3年左右,这个时候你去应聘的时候,你对应的叫p6 ,能理解吗,好这个能get到的老师扣个一来嗯,好的,那什么叫p7 呢。
p7 什么样子呢,如果你的项目组一共有20个人,他们一般会有几个p7 呢,三个两三个左右,这个p7 啊,它叫做四五个人的一个team leader,team leader。
这四个人里面很可能负责一个小模块群,一个子系统,在这个子系统里面最核心的这哥们p7 好多g,这次五个人谁要技术不懂了,找他要找他问,这个一般叫p7 ,这个一般的如果社招来说啊,基本上5年左右的。
那我在这个基础之上呢,什么叫p8 呢,还想继续听吗,阿里工作3年仍是p6 ,生脾气比较难,晋升这块是一个比较复杂的问题。
呃我我我原来曾经专门讲过晋升课啊,在我们整个体系里头,我也想把这个晋升这块给大家慢慢的讲起来,小公司管四个人特别多,你小公司的管四个人,他就成不了p7 呃,我想问你啊,就是我我就交给你。
我教你一个简单的怎么晋升的,在座的想听吗,有有没有有没有想听,想听听老哥一来就教你怎么去做晋升这件事,嗯大家听我说啊,就是说晋升这件事情呢,他第一个呢是要求你的是你的综合能力,他可能不单单要求是纯技术。
当然也有可能搞不正之风的,你跟说跟领导睡了,跟领导那个关系特别好,嗯那也也有可能,咱们除去这种情况,一般来说怎么晋升,我就想问你一句话,你好好想,现在呢有,五个p6 ,其中有一个人会升为p7 。
我们的指标就是这样的好,我问你谁会升为p7 ,同学们记着我一个答案,谁先去做p7 的事情,我再说一遍,谁先去做p7 的事情,谁升为p7 的可能性就越高,谁先站在p7 的角度考虑问题。
谁成为p7 的可能性就越高,不知道大家能不能听得懂,能不能听得进去,我是说一个人的真正的成熟,一个人真正的成熟是从他认真对待工作开始,你们可以每天都摸鱼,每天都划水,你可以不认真对待你自己的工作。
敷衍自己的工作,但是我告诉你,敷衍自己的工作等于敷衍自己的人生,敷衍工作没有关系,但是你的人生也是在同事在敷衍,这是你的时间,我希望你们能听进去,所以为什么有的职位叫p6 plus。
这个plus plus在哪,虽然他还是p6 ,但他已经开始逐步在做p7 的事情,为什么有的人叫p7 plus,虽然他还是在p7 ,但是他已经在做p8 的事情,好。
学生里有一个比较牛牛比较牛逼的脾气,你们想看看吗,来这会儿一定一定给老师听进去,好不好。
他这个这哥们儿是p7 的一个顶级薪水啊,就是他看这里,3年的大型系统架构的设计经验,团队管理经验,你就记住了,真正的团队管理其实是在p8 才有他p7 里面呢,一般这个团队呢你管理个四五个人比较简单的啊。
一般只有到p8 才有,然后分布式高并发高可用大数据量的系统架构设计经验和研发经验,对各种源码均深度阅读,和下面是一系列的关于个人技能的描述,呃我一会给你讲为什么叫p7 plus,不叫p8 。
120万年薪,大家慢慢做,大多数人现在是到不了这个年薪的,跟老师慢慢学,老师会逐步带你到这个年薪去啊,好多精通对这个课程里都有,不用不用不用担心啊,精通这个词也能用吗,嗯反正别人都在用,你可以不用。
当别人都在用精通,而你不在用的时候,你猜猜看站在面试官的角度,他会怎么看,拿大腿想想。
分布系统架构,海量数据架构,高并发的系统架构,高可用的架构,高性能的架构啊,到什么程度才算精通。
面试官问你,你能够答得出来,大老师给你今天给你讲课的程度就算精通了,能说出来怎么用,能说出来为什么这么用,你就可以叫精通了,你能能说来怎么用,能灵活使用,能说出来为什么。
这个简历能get一份吗,这个简历不能get一份,这个简历是咱们小伙伴的简历,也是我们呃最近目前在用的一个简历的模板,把他的简历真实简历当成模板了,呃,这个小伙呢。
他现有的一个状况其实是比他当时的这个状况还要牛逼的啊。
我我我给你找一下,这小伙目前是我教的最牛逼的一个学生了,跟他是一个亦亦师亦友的关系了,他大概在30岁还是31岁的时候嗯,退休了,公司给了5000万的股票,并且套现,套现5000万,退休了啊。
我的简历根本看不了,其实你简历靠不了的原因呢,这个应技能不足嘛,补上硬技能就可以了啊,呃如果大家感兴趣,也可以找个图去好好的读一读它关于p7 的,关于p6 的一个说法,呃那么能套现对,为什么不能。
如果给了5000万股票不能套现,小伙伴,这股票有屁用,虽然我在公司的最后一站了,有福之人,每次遇到不可控的过程,总有一个人站出来拉我一把,这个人谦虚嘛啊就是越牛逼的人呢会越谦虚,截个图可以截。
你不用截图,嗯老师这里都是公开的啊,这里面所有的大概1000份左右的那个就业信息,111 千份左右,没有一个是那个说给大家p过或者干嘛的,只是给大家引去了隐私的信息而已啊。