偏向锁与hashcode能共存吗?

我们知道,Java对象头的结构如下:

内容说明备注
Mark Word存储对象的Mark Word信息-
Class Metadata Address存储指向对象存储类型的指针-
Array Length数组的长度只有数组对象有该属性

其中,在32位下,Mark Word的存储结构如下:

锁状态23 bits2 bits4 bits1 bit2 bits
无锁状态identity hash code(首次调用)分代年龄001
偏向锁Thread IDepoch分代年龄101
轻量级锁指向线程栈中Lock Record的指针00
重量级锁指向监视器(monitor)的指针10
GC标记011

在64位下,Mark Word的存储结构如下:

锁状态25 bits31 bits1 bit4 bits1 bit2 bits
无锁状态unusedidentity hash code(首次调用)unused分代年龄001
锁状态54 bits2 bits1 bit4 bits1 bit2 bits
偏向锁Thread IDepochunused分代年龄101
锁状态62 bits2 bits
轻量级锁指向线程栈中Lock Record的指针00
重量级锁指向监视器(monitor)的指针10
GC标记011

由此可知,在无锁状态下,Mark Word中可以存储对象的identity hash code值。当对象的hashCode()方法(非用户自定义)第一次被调用时,JVM会生成对应的identity hash code值(生成方式参见参考博客2),并将该值存储到Mark Word中。后续如果该对象的hashCode()方法再次被调用则不会再通过JVM进行计算得到,而是直接从Mark Word中获取。只有这样才能保证多次获取到的identity hash code的值是相同的(由参考博客2可知,以jdk8为例,JVM默认的计算identity hash code的方式得到的是一个随机数,因而我们必须要保证一个对象的identity hash code只能被底层JVM计算一次)。

我们还知道,对于轻量级锁,获取锁的线程栈帧中有锁记录(Lock Record)空间,用于存储Mark Word的拷贝,官方称之为Displaced Mark Word,该拷贝中可以包含identity hash code,所以轻量级锁可以和identity hash code共存;对于重量级锁,ObjectMonitor类里有字段可以记录非加锁状态下的mark word,其中也可以存储identity hash code的值,所以重量级锁也可以和identity hash code共存。

对于偏向锁,在线程获取偏向锁时,会用Thread ID和epoch值覆盖identity hash code所在的位置。如果一个对象的hashCode()方法已经被调用过一次之后,这个对象还能被设置偏向锁么?答案是不能。因为如果可以的化,那Mark Word中的identity hash code必然会被偏向线程Id给覆盖,这就会造成同一个对象前后两次调用hashCode()方法得到的结果不一致。

HotSpot VM的锁实现机制是:

  • 当一个对象已经计算过identity hash code,它就无法进入偏向锁状态;
  • 当一个对象当前正处于偏向锁状态,并且需要计算其identity hash code的话,则它的偏向锁会被撤销,并且锁会膨胀为轻量级锁或者重量锁;
  • 轻量级锁的实现中,会通过线程栈帧的锁记录存储Displaced Mark Word;重量锁的实现中,ObjectMonitor类里有字段可以记录非加锁状态下的mark word,其中可以存储identity hash code的值。

参考博客:

1、https://www.cnblogs.com/twoheads/p/10150063.html jvm简介:偏向锁、轻量级锁和重量级锁

2、https://www.jianshu.com/p/be943b4958f4 Java Object.hashCode()返回的是对象内存地址吗?

3、https://www.zhihu.com/question/52116998/answer/133400077 当Java处在偏向锁、重量级锁状态时,hashcode值存储在哪

4、http://www.mamicode.com/info-detail-2601598.html  偏向锁浅析

5、https://blog.csdn.net/weixin_42213903/article/details/97044043 java 偏向锁

6、https://www.jianshu.com/p/6be2e37aca6f  Java中hashCode的实现

7、https://www.jianshu.com/p/e74fe532e35e JVM知识整理

  • 11
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值