死磕synchronized二:系统剖析延迟偏向篇一

简介: 近期准备写一个专栏:从Hotspot源码角度剖析synchronized。前前后后大概有10篇,会全网发,写完后整理成电子书放公众号供大家下载。对本专栏感兴趣的、希望彻彻底底学明白synchronized的小伙伴可以关注一波。电子书整理好了会通过公众号群发告知大家。我的公众号:**硬核子牙**。

哈喽,大家好,我是江湖人送外号[道格牙]的子牙老师。

近期准备写一个专栏:从Hotspot源码角度剖析synchronized。前前后后大概有10篇,会全网发,写完后整理成电子书放公众号供大家下载。对本专栏感兴趣的、希望彻彻底底学明白synchronized的小伙伴可以关注一波。电子书整理好了会通过公众号群发告知大家。我的公众号:硬核子牙

市面上关于synchronized的资料已经很多了,我这个专栏跟那些资料有啥差别呢:

  1. 更系统。市面上目前虽然资料众多,但都是零散的。有些资料讲得东西甚至是相互冲突的,都不知道信谁的。我准备从Java层面到JVM层面到操作系统层面系统的去分析用synchronized后呈现的每个现象背后的本质。synchronized很多知识点市面上是没有资料讲的,我给它补上。
  2. 更接近真相。市面上的很多资料,有的是基于字节码解释器那块的代码yy出来的,有的是东拼西凑整合出来的,各个说的都像真的一样,把看的人搞蒙圈了。我准备从模板解释器代码入手,单步调试着研究,有些不确定的自己写代码去证明,争取分享给大家的都是本来如此的知识。不确定的地方我会标注出来。
  3. 授人以鱼不如授人以渔。我会以大家学完后能够手写出synchronized的标准来设计这个专栏。因为从我自己研究的角度来说,抛开语言的障碍,synchronized的每种机制如果让你实现你手足无措,那你还是没有真正地理解synchronized。言外之意就是你不一定要去手写,但是你在脑海中回想,比如CAS、锁膨胀、锁对象加锁解锁……你大概知道代码是怎么写的。

本篇文章是第二篇,聚焦分析偏向锁延迟策略:

  1. 什么是延迟偏向
  2. 为什么需要延迟偏向
  3. 延迟偏向机制是怎样的
  4. 延迟偏向对锁膨胀的影响及证明
  5. 从Hotspot源码角度证明

内容有点多,分两篇发。

是什么

什么是偏向延迟呢?见名知意:偏向锁就算是开启的,也不是马上就可以用的,中间有个延时。

对应的JVM参数是BiasedLockingStartupDelay,默认是4秒,可通过-XX:BiasedLockingStartupDelay修改
image.png

为什么

不知道大家在看到JVM中有偏向延迟这个机制的时候,脑海中有没有冒出这么几个问题:1、为什么要搞个偏向延迟?2、这个延时是从什么时候开始计算的?从JVM启动时吗?

为什么要设计

先回答第一个问题。这个问题的答案在网上有很多版本,最权威的答案就是这段注释。翻译过来就是说:这是一个启动时间回归的解决方案。说人话就是这样做,JVM启动可以更快。
image.png

为什么会更快呢?按照注释的说法:因为JVM在启动期间会采取大量安全点来消除偏差。这跟偏向锁有啥关系?说下我的理解哈,不一定是JVM工程师设计此的初衷。安全点大家应该是很熟悉了,启用安全点会带来STW。而偏向锁的撤销与重偏向判断,也是需要启用安全点的,因为需要扫描所有线程的虚拟机栈,需要内存静止才能保证结果准确。而JVM在启动期间用到的锁,包括初始化很多类的过程中用的锁,都会经过偏向锁逻辑,如果没有偏向延迟,就会带来更多的STW,导致JVM启动时间过长。

多说一句,有点不好理解:启动期间启用安全点消除偏差是一种先行发生策略,是为了保证启动期间有互动的多个线程的业务先后顺序。跟为了追求低延时数据同步插入内存屏障触发即时回写内存是差不多的思想。

延时何时计算

看下上面的代码,如果有延时,就创建一个任务。偏向延迟就是在这个任务中完成的,是由WatcherThread执行的,延迟偏向以后,WatcherThread执行到任务的task方法,创建一个VM_Operation丢入VMThread的任务池队列,等待VMThread执行。如果木有延时,就很直接了,创建一个VM_Operation丢人VMThread的任务池队列,等待VMThread执行。
image.png

顺便吐槽下,这个延时实现相当复杂。总之,Hotspot源码里面,就没有简单的东西。作为局外人,有些地方,我是真的不解,为啥要搞那么复杂。比如偏向锁整个机制,也是复杂的一批。

那延时是从哪开始的呢?是WatcherThread执行到sleep方法开始的,因为计算剩余时间一定需要与当前时间进行对比。
image.png

锁类型

synchronized对应的锁类型有这些:

  1. 无锁
  2. 偏向锁
  3. 轻量级锁
  4. 重量级锁

image.png

这些锁存储在哪个位置呢?对象头中。Java的每个对象,在JVM中的结构如图。Mark Word区域就是对象头。展开来就是上图的样子
image.png

对锁膨胀的影响

好的答案从好的问题开始。对于这个问题,咱们从这几个问题开始着手:

  1. 延迟偏向之前创建的对象是什么锁
  2. 延迟偏向之后创建的对象是什么锁
  3. 创建的对象的锁是是如何被延迟偏向影响的。这个下篇讲
  4. 延迟偏向之后,之前创建的对象持有的锁会被批量修改吗
  5. 有或无延迟偏向,锁如何膨胀

延迟偏向之前创建的对象是无锁状态。细节下篇讲
image.png

延迟偏向之后创建的对象是未偏向的偏向锁。细节后面讲
image.png

延迟偏向之前创建的对象,延迟偏向后,是不会批量修改的。言外之意就是延迟偏向之前创建的对象是无锁,延迟偏向之后还是无锁。
image.png

延迟偏向之前是无锁,膨胀后不会经历偏向锁,会直接膨胀成轻量级锁
image.png

延迟偏向之后创建的对象是未偏向的偏向锁,经过synchronized就会变成偏向当前线程的偏向锁
image.png

关于synchronized的锁膨胀逻辑,后面写文章细讲。

结语

我是子牙老师,喜欢钻研底层,深入研究Windows、Linux内核、JVM。喜欢分享硬核知识,如果你也喜欢研究底层,喜欢硬核知识,关注我:硬核子牙。

相关文章
|
3月前
|
存储 Kubernetes 架构师
阿里面试:JVM 锁内存 是怎么变化的? JVM 锁的膨胀过程 ?
尼恩,一位经验丰富的40岁老架构师,通过其读者交流群分享了一系列关于JVM锁的深度解析,包括偏向锁、轻量级锁、自旋锁和重量级锁的概念、内存结构变化及锁膨胀流程。这些内容不仅帮助群内的小伙伴们顺利通过了多家一线互联网企业的面试,还整理成了《尼恩Java面试宝典》等技术资料,助力更多开发者提升技术水平,实现职业逆袭。尼恩强调,掌握这些核心知识点不仅能提高面试成功率,还能在实际工作中更好地应对高并发场景下的性能优化问题。
|
5月前
|
Java 调度
【多线程面试题 四】、 线程是否可以重复启动,会有什么后果?
线程不能被重复启动,一旦调用start()方法后,线程将从新建状态进入就绪状态,再次调用start()会抛出IllegalThreadStateException异常。
|
安全 算法 Java
可重入锁,不可重入锁,死锁的多种情况,以及产生的原因,如何解决,synchronized采用的锁策略(渣女圣经)自适应的底层,锁清除,锁粗化,CAS的部分应用
可重入锁,不可重入锁,死锁的多种情况,以及产生的原因,如何解决,synchronized采用的锁策略(渣女圣经)自适应的底层,锁清除,锁粗化,CAS的部分应用
|
安全 Java 测试技术
【JUC中的 “8锁现象” 】 —— 每天一点小知识
【JUC中的 “8锁现象” 】 —— 每天一点小知识
144 0
【JUC中的 “8锁现象” 】 —— 每天一点小知识
|
存储 安全 算法
《我要进大厂》- Java并发 夺命连环10问,你能坚持到第几问?(进程&线程 | 并行&并发 | 上下文切换 | 线程死锁 | 线程创建)
《我要进大厂》- Java并发 夺命连环10问,你能坚持到第几问?(进程&线程 | 并行&并发 | 上下文切换 | 线程死锁 | 线程创建)
《我要进大厂》- Java并发 夺命连环10问,你能坚持到第几问?(进程&线程 | 并行&并发 | 上下文切换 | 线程死锁 | 线程创建)
|
数据采集 缓存 算法
库调多了,都忘了最基础的概念 《锁与线程 2 终结篇》
库调多了,都忘了最基础的概念 《锁与线程 2 终结篇》
146 0
库调多了,都忘了最基础的概念 《锁与线程 2 终结篇》
|
存储 安全 Java
看完你就明白的锁系列之锁的状态
前面两篇文章我介绍了一下 看完你就应该能明白的悲观锁和乐观锁 看完你就明白的锁系列之自旋锁 看完你就会知道,线程如果锁住了某个资源,致使其他线程无法访问的这种锁被称为悲观锁,相反,线程不锁住资源的锁被称为乐观锁,而自旋锁是基于 CAS 机制实现的,CAS又是乐观锁的一种实现,那么对于锁来说,多个线程同步访问某个资源的流程细节是否一样呢?换句话说,在多线程同步访问某个资源时,锁的状态会如何变化呢?本篇文章来探讨一下。
104 0
看完你就明白的锁系列之锁的状态
|
存储 NoSQL Java
看看我给面试官是如何娓娓道来synchronized锁升级过程的
看看我给面试官是如何娓娓道来synchronized锁升级过程的
176 0
看看我给面试官是如何娓娓道来synchronized锁升级过程的
J3
|
存储 安全 Java
synchronized解析及锁膨胀过程,面试再也不怕了
synchronized解析及锁膨胀过程,面试再也不怕了
J3
555 0
synchronized解析及锁膨胀过程,面试再也不怕了
|
算法 Java Linux
如果面试官让你分析类初始化阶段的死锁现象
哈喽,我是子牙。十余年技术生涯,一路披荆斩棘从技术小白到技术总监到JVM专家到创业。技术栈如汇编、C语言、C++、Windows内核、Linux内核。特别喜欢研究虚拟机底层实现,对JVM有深入研究。分享的文章偏硬核,很硬的那种。
100 0
如果面试官让你分析类初始化阶段的死锁现象

热门文章

最新文章

相关实验场景

更多