Java面试synchronized偏向锁后hashcode存址
作者:猪哥66 时间:2023-08-09 09:15:06
前言
今天的文章从下面这张图片开始,这张图片Java开发们应该很熟悉了
我们都知道无锁状态是对象头是有位置存储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方法时才会放进对象头。
第一次打印的对象头中我们发现对象头中mark word值为16进制的5,转为2进制就是101,且后面的状态显示为biasable,也就是可偏向,注意区分可偏向和已偏向:可偏向表示还么有synchronized锁,已偏向表示有线程访问锁。
第二次打印对象头中已经存在hashcode,value为0x00000039a054a501,转换为2进制为:11100110100000010101001010010100000001,最后三位也就是0 01,这就表示不可偏向,也就说当出现synchronized锁不会进行偏向,真是如此吗?我们验证一下!
2、存在hashcode后,出现synchronized会是什么锁?
根据下图我们可以清晰的看到,当已存在hashcode再执行同步代码,则会直接进入轻量级锁,原因还是上面的结论,有hashcode后将锁设置为 不可偏向,那肯定就直接上轻量级锁咯。
3、如果锁状态是 已偏向,再计算hashcode会怎样?
前面两种情况锁状态都是 可偏向 状态,如果此时锁状态是 已经进入偏向状态呢?是会进行锁升级嘛?
根据下图我们可以看到,当hashCode方法处于synchronized代码块中时,锁直接升级为重量级锁。
至于为什么直接升级为重量级锁而不是轻量级锁,这个原因不得而知。
猪哥猜想可能无线程竞争状态下,偏向锁升级为重量级锁消耗的资源比轻量级锁消耗的资源少。
同时欢迎知道原因的同学能够留言告知,也欢迎大家说出自己的猜想?没准以后会根据你的方案优化呢!
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
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
SpringMVC bean加载控制的实现分析
![](https://img.aspxhome.com/file/2023/2/57912_0s.png)
Spring MVC 关于controller的字符编码问题
Java Comparable及Comparator接口区别详解
![](https://img.aspxhome.com/file/2023/5/57425_0s.png)
JAVA实现长连接(含心跳检测Demo)
谈谈为JAXB和response设置编码,解决wechat4j中文乱码的问题
![](https://img.aspxhome.com/file/2023/1/57621_0s.png)
Flutter刷新组件RefreshIndicator自定义样式demo
![](https://img.aspxhome.com/file/2023/2/58272_0s.webp)
SpringCloud如何创建一个服务提供者provider
![](https://img.aspxhome.com/file/2023/3/57813_0s.png)
flutter material widget组件之信息展示组件使用详解
复杂JSON字符串转换为Java嵌套对象的实现
记一次springboot服务凌晨无故宕机问题的解决
![](https://img.aspxhome.com/file/2023/9/57589_0s.jpg)
Java关键字instanceof的两种用法实例
Android TextView实现跑马灯效果的方法
![](https://img.aspxhome.com/file/2023/3/84733_0s.jpg)
详解Spring ApplicationContext加载过程
C++实现leetcode(3.最长无重复字符的子串)
详解基于spring多数据源动态调用及其事务处理
![](https://img.aspxhome.com/file/2023/0/57530_0s.png)
Flutter 如何正确显示SnackBar
Java实战之实现一个好用的MybatisPlus代码生成器
![](https://img.aspxhome.com/file/2023/8/57498_0s.png)
Android 消息机制详解及实例代码
![](https://img.aspxhome.com/file/2023/3/85963_0s.png)