死磕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。喜欢分享硬核知识,如果你也喜欢研究底层,喜欢硬核知识,关注我:硬核子牙。

相关文章
|
14天前
|
存储 监控 安全
解锁ThreadLocal的问题集:如何规避多线程中的坑
解锁ThreadLocal的问题集:如何规避多线程中的坑
23 0
|
6月前
|
安全 算法 Java
可重入锁,不可重入锁,死锁的多种情况,以及产生的原因,如何解决,synchronized采用的锁策略(渣女圣经)自适应的底层,锁清除,锁粗化,CAS的部分应用
可重入锁,不可重入锁,死锁的多种情况,以及产生的原因,如何解决,synchronized采用的锁策略(渣女圣经)自适应的底层,锁清除,锁粗化,CAS的部分应用
|
10月前
|
安全 Java 测试技术
【JUC中的 “8锁现象” 】 —— 每天一点小知识
【JUC中的 “8锁现象” 】 —— 每天一点小知识
【JUC中的 “8锁现象” 】 —— 每天一点小知识
|
11月前
|
存储 安全 Java
大白话讲解synchronized锁升级套路
synchronized锁是啥?锁其实就是一个对象,随便哪一个都可以,Java中所有的对象都是锁,换句话说,Java中所有对象都可以成为锁。 这次我们主要聊的是synchronized锁升级的套路
|
存储 安全 Java
看完你就明白的锁系列之锁的状态
前面两篇文章我介绍了一下 看完你就应该能明白的悲观锁和乐观锁 看完你就明白的锁系列之自旋锁 看完你就会知道,线程如果锁住了某个资源,致使其他线程无法访问的这种锁被称为悲观锁,相反,线程不锁住资源的锁被称为乐观锁,而自旋锁是基于 CAS 机制实现的,CAS又是乐观锁的一种实现,那么对于锁来说,多个线程同步访问某个资源的流程细节是否一样呢?换句话说,在多线程同步访问某个资源时,锁的状态会如何变化呢?本篇文章来探讨一下。
78 0
看完你就明白的锁系列之锁的状态
|
NoSQL 算法 关系型数据库
并发编程不能避开的“锁”事
本文主要介绍在日常多任务或者分布式系统开发中,为了同步访问共享资源,设置的各种锁。涵盖了Linux系统的锁,JAVA锁,Mysql锁以及分布式锁等内容。
139 0
并发编程不能避开的“锁”事
Synchronized 升级到重量级锁之后就下不来了?你错了!
Synchronized 升级到重量级锁之后就下不来了?你错了!
Synchronized 升级到重量级锁之后就下不来了?你错了!
J3
|
存储 安全 Java
synchronized解析及锁膨胀过程,面试再也不怕了
synchronized解析及锁膨胀过程,面试再也不怕了
J3
489 0
synchronized解析及锁膨胀过程,面试再也不怕了
|
安全 前端开发 Java
十分钟带你深入了解多线程——多线程关于锁的优化(一)
十分钟带你深入了解多线程——多线程关于锁的优化(一)
266 0
|
安全 Java 数据安全/隐私保护
【高并发】高并发环境下诡异的加锁问题(你加的锁未必安全)
在并发编程中,不能使用多把锁保护同一个资源,因为这样达不到线程互斥的效果,存在线程安全的问题。相反,却可以使用同一把锁保护多个资源。那么,如何使用同一把锁保护多个资源呢?又如何判断我们对程序加的锁到底是不是安全的呢?我们就一起来深入探讨这些问题!
327 0
【高并发】高并发环境下诡异的加锁问题(你加的锁未必安全)

相关实验场景

更多