性能文章>死磕synchronized三:系统剖析延迟偏向篇二>

死磕synchronized三:系统剖析延迟偏向篇二原创

3671323

哈喽,我是子牙。十余年技术生涯,一路披荆斩棘从技术小白到技术总监到JVM专家到创业。技术栈如汇编、C语言、C++、Windows内核、Linux内核。特别喜欢研究虚拟机底层实现,对JVM有深入研究。分享的文章偏硬核,很硬的那种。

 

手撸过JVM、内存池、垃圾回收算法、synchronized、线程池、NIO…

 

 

关于分析偏向锁延迟策略:

  1. 什么是延迟偏向

  2. 为什么需要延迟偏向

  1. 延迟偏向机制是怎样的

  2. 延迟偏向对锁膨胀的影响及证明

  1. 从Hotspot源码角度证明

 

上篇已经分享了绝大部分内容,本篇就把剩下的补上。本篇文章是从Hotspot源码角度分析延迟偏向机制:

  1. 新创建的对象的锁是是如何被延迟偏向影响的

  2. 延迟偏向之前加载的类的初始锁是什么锁

  3. 延迟偏向之后加载的类是无锁还是偏向锁

 

01

对象初始锁

新创建的对象的初始锁是如何确定的,直接看Hotspot源码

 

 

JVM创建对象的步骤是先申请内存,然后对这块内存进行数据填充。数据填充包括设置对象头。这个方法就是在数据填充阶段调用的。代码逻辑很简单,如果启用了偏向锁,则将这个oop对应的klass的属性property_header作为初始锁填充进去。如果没有启用偏向锁,则生成一个无锁作为初始锁填充进去。

 

免得有小伙伴没看过我之前的文章或视频,不知道oop与klass,做个简单的解释:Hotspot主要部分是由C++编写的,oop就是Java对象对应的C++实例,klass就是Java类对应的C++实例。

 

正常情况下偏向锁都是开启的,那创建的对象的初始锁最终受限于延迟偏向,再细化一点说是受限于创建对象基于的这个klass是在延迟偏向之前加载的还是之后。接下来咱们就看看下面三种情况底层是如何实现的:

  1. 基于延迟偏向之前加载的类,在延迟偏向之前创建的对象初始锁是无锁

  2. 基于延迟偏向之前加载的类,在延迟偏向之后创建的对象是偏向锁

  3. 基于延迟偏向之后加载的类,创建的对象都是偏向锁

 

02

延迟偏向前

首先,延迟偏向之前所有加载的类默认是无锁,所以延迟偏向之前所有创建的对象都是无锁,核心代码如下

 

 

那延迟偏向之前加载的类,延迟偏向之后创建的对象为什么是偏向锁呢?看代码

 

 

JVM在启动的时候调用了BiasedLocking::init,这个方法会创建一个VM_Operation塞入VMThread的任务队列中,经历偏向延迟后才会被执行。执行的内容就是遍历之前加载的所有的类,将它们的属性property_header改为偏向锁,即biased_locking_prototype。

 

VMThread在执行这个方法期间,就是还在执行classes_do方法,还未将_biased_locking_enabled设为TRUE,这个时候发生了类加载,那这时候加载的类生成的对象就永远是无锁状态了。为了这个问题我还特意梳理了下代码,发现JVM为了避免这个问题,执行这个方法之前是会启用安全点创造STW环境的。

SafepointSynchronize::begin();
evaluate_operation(_cur_vm_operation);

 

03

延迟偏向后

新加载的类默认都是无锁,如果是延迟偏向之前加载的类,会在延迟偏向之后,由VMThread将其改为偏向锁,从而影响基于这个类创建的对象的锁状态。那基于延迟偏向之后加载的类创建的对象是偏向锁,是为什么呢?

 

第一种可能是:加载的类是无锁,已经过了延迟偏向时间了,就不会有其他程序来改类的锁状态,所以是在创建对象填充的时候修改的。这个其实从上面介绍新创建的对象的初始化填充就已经可以正式了。所以这种可能pass。

 

所以只剩这种可能,加载的类的锁在加载期间被改掉了,改成了偏向锁,按照这个分析我单步调试Hotspot源码找线索,终于找到了核心代码

 

 

至此,延迟偏向相关的知识点就全部给大家讲完了。

 

04

系列文章

1、JVM如何执行synchronized修饰的方法

2、系统剖析延迟偏向篇一

 

05

推荐阅读

1、技术人如何才能拿到百万年薪?

2、为什么他们成为了技术大牛?

3、深入剖析Lambda表达式的底层实现原理

 

 

我有话说

 

我是子牙。十余年技术生涯,一路披荆斩棘从小白到技术总监到大厂中间件到创业。技术栈如汇编、C语言、C++、Windows内核、Linux内核及特别喜欢研究虚拟机底层实现,对JVM有深入研究。分享的文章偏硬核,很硬的那种。不考虑交个朋友吗?关注硬核子牙:

点赞收藏
分类:标签:
子牙_公号硬核子牙

对编程语言的设计与实现有浓厚兴趣。聚焦Hotspot源码、Linux内核研究,硬核干货分享

请先登录,查看3条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

从 Linux 内核角度探秘 JDK MappedByteBuffer

从 Linux 内核角度探秘 JDK MappedByteBuffer

MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异

MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异

23
3