Java面试synchronized偏向锁后hashcode存址

作者:猪哥66 时间:2023-08-09 09:15:06 

前言

今天的文章从下面这张图片开始,这张图片Java开发们应该很熟悉了

Java面试synchronized偏向锁后hashcode存址


我们都知道无锁状态是对象头是有位置存储hashcode的,而变为偏向锁状态是没有位置存储hashcode的,今天我们来通过实现验证这个问题:当锁状态为偏向锁的时候,hashcode存到哪里去了?

先说结论:

  • jdk8偏向锁是默认开启,但是是有延时的
    可通过参数: -XX:BiasedLockingStartupDelay=0关闭延时。

  • hashcode是懒加载,在调用hashCode方法后才会保存在对象头中。

  • 当对象头中没有hashcode时,对象头锁的状态是 可偏向( biasable,101,且无线程id)。

  • 如果在同步代码块之前调用hashCode方法,则对象头中会有hashcode,且锁状态是 不可偏向(0 01),这时候再执行同步代码块,锁直接是 轻量级锁(thin lock,00)。

如果是在同步代码块中执行hashcode,则锁是从 偏向锁 直接膨胀为 重量级锁。

1、hashcode是啥时候存进对象头中?

根据下图我们可知,hashcode并不是对象实例化后就创建,而是在调用默认的hasCode方法时才会放进对象头。

Java面试synchronized偏向锁后hashcode存址

第一次打印的对象头中我们发现对象头中mark word值为16进制的5,转为2进制就是101,且后面的状态显示为biasable,也就是可偏向,注意区分可偏向和已偏向:可偏向表示还么有synchronized锁,已偏向表示有线程访问锁。

第二次打印对象头中已经存在hashcode,value为0x00000039a054a501,转换为2进制为:11100110100000010101001010010100000001,最后三位也就是0 01,这就表示不可偏向,也就说当出现synchronized锁不会进行偏向,真是如此吗?我们验证一下!

2、存在hashcode后,出现synchronized会是什么锁?

根据下图我们可以清晰的看到,当已存在hashcode再执行同步代码,则会直接进入轻量级锁,原因还是上面的结论,有hashcode后将锁设置为 不可偏向,那肯定就直接上轻量级锁咯。

Java面试synchronized偏向锁后hashcode存址

3、如果锁状态是 已偏向,再计算hashcode会怎样?

前面两种情况锁状态都是 可偏向 状态,如果此时锁状态是 已经进入偏向状态呢?是会进行锁升级嘛?

根据下图我们可以看到,当hashCode方法处于synchronized代码块中时,锁直接升级为重量级锁。

Java面试synchronized偏向锁后hashcode存址

至于为什么直接升级为重量级锁而不是轻量级锁,这个原因不得而知。

猪哥猜想可能无线程竞争状态下,偏向锁升级为重量级锁消耗的资源比轻量级锁消耗的资源少。

同时欢迎知道原因的同学能够留言告知,也欢迎大家说出自己的猜想?没准以后会根据你的方案优化呢!

4、总结

  • jdk8偏向锁是默认开启,但是是有延时的,可通过参数: -XX:BiasedLockingStartupDelay=0关闭延时。

  • hashcode是懒加载,在调用hashCode方法后才会保存在对象头中。

  • 当对象头中没有hashcode时,对象头锁的状态是 可偏向( biasable,101,且无线程id)。

  • 如果在同步代码块之前调用hashCode方法,则对象头中会有hashcode,且锁状态是 不可偏向(0 01),这时候再执行同步代码块,锁直接是 轻量级锁(thin lock,00)。

  • 如果是在同步代码块中执行hashcode,则锁是从 偏向锁 直接膨胀为 重量级锁。

来源:https://blog.csdn.net/u014044812/article/details/124302959

标签:java,synchronized,偏向锁,hashcode,存址
0
投稿

猜你喜欢

  • C#使用有道ip地址查询接口方法实例详解

    2022-10-08 22:07:31
  • android 通过MediaRecorder实现简单的录音示例

    2023-07-29 06:03:54
  • 简单记录C# 条件编译

    2023-10-20 05:49:07
  • C# 对XML基本操作代码总结

    2022-08-21 16:09:09
  • springboot+mybatis+redis 二级缓存问题实例详解

    2022-08-09 09:06:36
  • 只需两步实现Eclipse+Maven快速构建第一个Spring Boot项目

    2023-08-03 23:47:43
  • Spring Boot整合Spring Data JPA过程解析

    2023-08-23 00:12:27
  • 如何在IDEA Maven项目中导入本地jar包的步骤

    2023-03-25 06:43:48
  • Java 抽象类与接口的对比

    2022-05-31 08:28:30
  • C++ 二维(多维)vector添加一个空项问题

    2022-10-10 14:44:23
  • Java中Jackson快速入门

    2023-01-18 10:24:44
  • 详解Java的回调机制

    2023-07-27 07:17:43
  • Java 中String StringBuilder 与 StringBuffer详解及用法实例

    2021-06-17 12:25:32
  • Android实现Path平滑的涂鸦效果实例

    2023-12-11 23:07:45
  • spring拓展之如何定义自己的namespace

    2022-01-12 05:13:33
  • C#使用DirectX.DirectSound播放语音

    2022-08-28 01:22:33
  • 学生信息管理系统java版

    2023-06-16 15:48:10
  • Java Web开发之基于Session的购物商店实现方法

    2023-06-09 20:46:35
  • Android悬浮按钮点击返回顶部FloatingActionButton

    2021-09-09 01:47:00
  • Android实现图片的裁剪(不调用系统功能)

    2021-05-25 23:26:41
  • asp之家 软件编程 m.aspxhome.com