00:00
接下来各位同学给大家介绍一下偏向所的持有那么对应的理论和落地的技术实现,来,请看说明。我们在实际的应用过程中发现,所总是同一个线程持有,很少发生竞争,也就是说所总是被第一个占用它的线程所拥有,那么这个线程就是锁的是吧?偏向线程,那么根据刚才我们所说的对吧,大规模是不是都是由同一个线程所抢到,比方说这次B以后的全部都是aaaaa所抢到,那么这样的话是程序它底层自我优化,就是尽量让同一个线程获得,对吧?减少这个频繁的切换。那么我们只需要在锁的第一次被拥有的时候记录下偏向线程ID,那比如说刚才的这个A,我们就把它记录进我们的这个偏向线程ID,假设啊,这个就是线程ID,就是A这个线程,那么这样。偏向所呢,就一直持有着所。
01:00
后续这个线程进入和退出这段加了同步锁的代码的时候,不需要再次加锁示放就节约了这些申请加锁,用完示范锁这些繁锁的过程,直接就像我们刚才所说的,打透了老规矩点菜对吧?所以说呢,他就会直接去检查,只要是锁的mawa里面放的是不是自己这个现场ID,如果是自己说明还是我老规矩走起,如果不是,那么是另外一种情况,那么可能有别的线程进来要竞争了,好,那么下面请看,如果相等,就表示偏向索,偏向于当前线程还是同一个,那么我第一次啊,存进去是A,第二次来的时候发现,哎,这个线程是A是吧,那么还是它那么。我们呢,就偏向于当前线程,不需要再尝试获得所节约了上面这些过程,直到发生竞争才会释放所。那么以后每次同步。检查所的偏向线程的ID与当前线程的ID是不是一样的,如果里面存的是和我现在所访问的都是同一个,那么就一致,那么所以说干嘛?
02:07
直接进入同步,无需每次加解锁都去CS更新对象头,就不用这些繁琐的了。如果自始至终使用的锁,这个线程有且仅有一个,那么很明显偏向所几乎没有额外的开销,性能极高,对吧?好,那么这个是相等,那但是如果不相等呢?那说明什么?有竞争了,比如说刚才我们所说的,我这个A县城都喜欢去做三号桌子啊,然后呢,老规矩点那几样老菜,但是突然发现今天三号桌子哎,李四过来做了,那么这个时候说明什么?不相等,有可能发生了竞争,那么所已经不是总是偏向于同一个线程了。有可能会换人咯,这个时候会尝试使用什么cns来替换马?Word里面的现场ID为新线程ID,好,如果竞争成高,那表示之前的线程不存在了,Mawa里面的线程ID为新的线程ID所,不会升级,仍然为偏向所,那假设啊。
03:10
以前呢,是只有一个线程,哎,来反问,突然,那么同学们我们也会发现什么着,偶尔是不是也会有B对吧,这个很正常,那么所以说这个时候我们会发现。假设现在存的是A在里面用着呢,有竞争了,B过来了,CS发现又不是我自己,那么这个时候他可能在外面自学,要准备过来,那么假设A用完了以后,刚好也就不再用了,那么相当于说什么。江山易主,由A变成B,前50次啊,假设都是A,然后A用完了以后。彻底走了,又从A变成了B,还是同一个线程,也没有其他线程来跟B来进行抢,只不过当前线程指针由A换成了B,那么也就是我们这儿所说的进程乘高,表示之前的线程A不存在了,这markwa里面的线程ID为信线程的ID,假设我们刚才所说的B,所以不会升级,还是偏向,只不过从偏向A到偏向了B,因为现在还是一个线程,但是抱歉,如果这个时候。
04:08
A在里面没走,B过来竞争失败,那么相当于说这个时候我们会发现竞争失败了,有可能就要升级,那么就是后面的我们要升级为轻量所,那么才能保证县城之间公平的竞争所。注意,我们会得到一个结论是什么偏向所?只有遇到什么其他线程尝试竞争的时候,它才会释放,否则的话,它不会主动释放偏向锁。那么也就是说有且仅有一个线程的时候,Java虚拟机底层会做优化,尽量让同一个线程获得频繁的让它拿到,不要让它干嘛发生竞争,避免这个切换。所以偏向所只发生在什么?竞争的时候才会出现,OK,那么这个就是他们对应的理论,那么技术上呢,我们是这么干的。假设一个S方法被一个线程强到了假设线程A啊,那么这个方法所在的对象就会在其所在的mark word中将偏向所的状态为修改,那么这个时候我们从0015所变成了101要加这个偏向锁,同时还会占用前54位来存储线程指针作为标识,说明现在AA线程站在这儿。
05:21
都偏向于它,如果线程再次访问同一个块时,这个线程就只需要去对象头里面去看看,现在A又来访问了,看看我这个偏向所里面是不是还是自己,如果是自己,那么说明什么?基本上就是相等,那么就是还是要偏向于当前线程,无需再尝试重新获得所,那么这样的话呢,干嘛一样判断一下是否有偏向所指向本身这个ID无需再进入模拟塔去竞争对象,那么这样是不是就不用同到重量极所,我们这样的话呢,程序呢,更加的柔和一些,性能更好,OK,好,这个就是偏向组的持有。那么接下来我们细化一下案例,假设我们有个对象叫account,来这个对象来给大家说明一下。
06:04
首先。偏向所的操作不用直接同道操作系统,就是尽量不要涉及用户态到内核态的转换,不必要直接升级为最高级的重量级锁,我们以一个account对象的对象头为例,好,同学们请看,我们大家都知道account对象我列了这么一个账户,那么现在是不是有对象头实例数据和对齐填充,那么现在假设我就是普普通通的一个无锁的状态,那么我这个数据是不是存在一些哈西扣的呀,分带年龄啊,偏向的状态的标志啊,那么就是001,那么跟我们这儿一样001,好,那么接下来。假如有一个线程执行到CMA代码块的时候,Java虚拟机会使用CS操作,把线程的指针ID记入到ma当中,那么好,我们现在过来这儿有一个线程来获得了,我希望里面就跟我们自选所一样,没有人。占用这个锁是,那果然也是,那我A圈强到,那么我是不是就修改偏向标记,从001变成101,标示当前线程。
07:06
获得对象所,对象变成偏向所。那么字面意思就是偏向于第一个获得它线程的这个锁,执行完同步代板块以后,线程怎么着并不会主动释放这个偏向锁,那么这个时候我呢一标识为101,而且把前面的这个数据改成了什么,使有这个锁的当前线程ID,那么这个时候线程获得锁就可以执行同步代码块二。当线程第二次到达的时候,会判断此持有锁这个线程是否还是自己,你就看看是不是还是自己的这个记录,OK,那么持有锁的线程ID也在对象头里面,那么这个Java虚拟机就会对account对这个对象的mark word进行判断,如果相等,说明这个线程还在,说明还持有这个对象的锁,就可以继续进入临界区,不用频繁的切换,对吧?哟,还是你来啦,老规矩,走吧。由于之前没有释放过锁,所以说这也不用重新申请加锁,如果自始至终使用锁的线程几个只有一个,那么很明显偏向所呢几乎就没有额外的开开销,性能极高。所以说我们的结论。
08:14
Java虚拟器不用和操作系统协商,设置没text lock就是这种内核态的这个动作没到内存呢,我们自己内部就解决了,它只需要记录一下线程ID,就表示自己获得了当前锁,不用进入操作系统,避免了从用户态进入到内核态,所以偏向就是在没有其他线程竞争的时候一直偏心。偏向同一个当前线程,当前线程就一直可以一直执行,一直可以使有这个锁,那么避免了频繁的切换,好,那么同学们,这个就是我们偏向所石油所的一个过程和相关的细节。
我来说两句