00:00
大家好,接下来给大家介绍第二种锁偏向锁来。老规矩。我们呢,先介绍偏向锁的理论,它能干些什么,怎么出来的,然后再结合我们价虚拟机64位马二的对象头的标识,来演示一下所得状态的变更和升级情况,好走起。什么叫偏向所注意单线程竞争哎。开篇名义几个线程,一个还没到特别剧烈的多并发高并发竞争了,那么也就是说,假设某一段同步代码块它也加锁了,它从无锁也到开始加锁了,但是现在只有一个线程来访问。那么他呢,来的时候就像现在呢,这个卫生间没有人,只有杨哥一个人进去,那么通过操作修改对象头的markwa中对应的偏向ID,开启偏向模式,如果不存在其他线程竞争的话,那么持有偏向组的线程将永远不需要。
01:02
进行同步,那这个是什么意思呢。来换,我们以前大家都清楚,多线程来竞争同一个资源类的时候,为了避免大家程序出错。超买超慢一定会加SOK,那么假设没有现在什么偏向锁啊,轻量锁这些优化,那换以前我们晓得的,那么就是什么频繁的。出现什么呢?也就是我们的用户他。到。内核态的切换,OK,那么假设啊,ABCDEFG很多个线程,那每个人都要轮一次啊,每次都是不同的人,哎,咱也就认了,那这个没办法,但是突然发现在多线程高并发的进程当中。很大一段情况,有可能大家在抢的时候,第一次抢到的是二号线程,第二次抢到的还是他,第三次抢到的还是他,会出现这样。
02:04
大规模。并发访问的情况下,抢到线程的可能会是什么?同一个线程,那么这个时候有点类似于什么?第一次是你,第二次是你,第三次还是你,那么这样的话,如果都是同一个的话,我们是不是就不再需要每次频繁的加锁解锁,加锁解锁用户态内核态,用户态内核态,那么这样的切换我们是不是尽量的给它减少一些,只要对同一个现场而言的话,那么这样的话是不是就可以提升我们的效率,避免频繁的用户态和内核态来进行切换,达到我们优化程序的目的呢?答案是肯定的。所以我们这儿它的作用就是。当一段同步代码一直被几个同一个线程是吧?多次访问的话,由于只有一个线程,那么该线程在后续访问时便会自动获得锁,不再需要。
03:04
重量所类似的用户态到乐和态这样的频繁切换,OK,那么举个小例子,弟兄们假设。你呢?现在长期去一家饭店吃饭?第一次去,假设就坐三号桌子,服务员过来。这位顾客点菜吧,那么你说第一次啊,那么大家呢,肯定是要从用户态到内核态,对吧,有点类似于说我们第一次呢,还不熟悉,你点了宫保鸡丁一份,酸辣土豆丝一份,再加一碗米饭好了,那么现在兄弟们。你这个状态点清楚了,进来OK,然后呢又离开,没问题,第二天你又过去吃饭了,那么服务员呢,又发现还是你好,依旧先生今天吃点什么,你呢?宫保,鸡丁,土豆丝,一碗米饭,OK,第三次,第四次,第五次,第十次以后,突然发现来来回回你都是坐这个位置,都点同样的菜,那么保不起。
04:07
服务员和你之间见面三分熟吗?慢慢的发现都是你来这儿吃,这个座位,这个时间点,而且都点这几样菜。突然有一天服务员会问你,先生老规矩,你点点头,是的,那么这样的话,是不是服务员连菜单都不用写马上?就明白你想点什么菜,你要做什么事,所以说这样一种情况,是不是就不用再像第一次来这样的,哎,服务员要在菜单上写好宫爆鸡丁一份,忌口是什么,土豆丝是一份,做到几分熟,米饭要的是什么样的,哎,不用那么多了,老规矩三个字啊,是不是就替代了,所以说这个时候它的意思就是什么。你这一段同步代码一直被同一个多访问,那么就不再进行频繁的切换了,直接自动获得,OK,所以说呢,我们这儿呢。同一个老顾客来访,跟生活中的案例一样,直接老规矩,走个方便,服务员也不用频繁的去写单子了,直接跟后海出三号客人,老规矩,OK,收到大家都明白,那么这样是不是就可以自动获得你最佳的效果?那么来,这是我们的生活的案例,那么口说无凭代码说话,那么来,同学们。
05:16
我们呢,先写好一个卖票的案例啊,这个呢就是最简单的,我们就节约时间了,那么三个售票员卖出50张票,50张票对象,那么这S同步代码块好来卖票,三个售票员。运行一下程序。来同学们后台我们来看一下啊,调整一下这个。给它移动一下啊。好,同学们露眼。哎。B。又变成aaaaaaa,大家有没有发现大部分时候都是同一个线程所获得,好,我们再执行一次。这个时候同学们请看。AAABB两次又变成aaaaa,有没有发现这个时候就是我们刚才所说的,表面上是三个线程C,可能这两次运行以后连抢到的机会都没有,AB就瓜分了,而且A抢到了多少次?就以本次程序为例,50次里面48次。
06:17
都是A,两次是B,所以说我们会发现就是大部分时候都是只有一个线程在获得一个资源内都是他抢的,所以呢,我们呢,你试想一下,你如果长期按照刚才我所说的生活案例。48次了,都去到这个饭店去吃饭,也许他不用48次,那么这个时候是不是饭店的服务员就会发现先生对你微笑一下又来了,老规矩,你说是的,那么这样的话,是不是直接就安排后厨给你做你以前所希望的那种模式和那样的菜单,那么这样是不是就不用平凡的记录变更,然后呢,加锁解锁,拥护它内核它,这样是不是就提升了性能,所以呢?到这儿我们会发现。
07:00
我们通过多线程卖票的案例就体会了什么叫。当一段同步代码一直被同一个线程多次访问,目前我们是不是都是被A抢到,那么由于只有一个线程多次拿到,那么干脆我们给他底层做一下优化,那么现在是不是就是我们所谓的有点偏心,你没有ABC3个售票员,雨露均沾大部分都是什么?A拿到了,所以我们得到一个结论,这样的话,这个A我们就不要48次都让它从用户态切换到内核态,假设只有一个线程,多次抢到同一把锁的时候,我们尽量的就会这么干。或者support作者经过研究发现,多数情况下,即便是在多线程情况下,这个锁不仅不存在多线程之间的竞争。还存在所有同一个线程怎么着多次获得的情况,来,同学们,我们现在这个S同步代码块没有出现ABCABCABC这种雨露均沾平均分配。相关的情况吧,都是A抢到符合吧,所以偏向所就是在这种情况下出现的,那么既然是多次被同一个线程。
08:09
所获得,那么我们就干脆就不要让它频繁的同步,那么这样的话就是可以同时提高我们的性能,那么也即偏向所会偏向于第一个访问锁的这个线程,如果在接下来运行过程当中,这个锁没有被其他的线程所访问。则持有偏向锁的线程永远不需要触发同步,哎,到后面这个A就越跑越顺,相当于没有加锁一样,OK,相当于说。消除了同步语句,那当然啊,实际上而言,这个语法上是肯定是写着的,但是呢,哎呀,见面三分熟我都明白了,老规矩对吧,所以说呢,你没有详细的点菜,但是我知道你想吃什么了,所以他懒得连CS都不用做了,直接就提升了程序性能,那么这个就是我们什么偏向锁的主要功能,OK,也是为了提升性能和效率非常好,那么来。
09:04
64位图我们就要看一下了,首先从无所到偏向所。那么。前54位就存当前线程指针的。Java thread从当前线程这个指针最后八位,那么呢,末尾的三个改成了多少?101代表从五所变成了偏向所,OK,好,那么同学同学们,这个就是我们偏向所相关所需要给大家的证明,那么下面我们来说一下偏向所的持有。
我来说两句