前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >偏向锁与hashcode能共存吗?

偏向锁与hashcode能共存吗?

作者头像
saintyyu
发布2021-11-22 09:57:44
4160
发布2021-11-22 09:57:44
举报
文章被收录于专栏:IT专栏

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

内容

说明

备注

Mark Word

存储对象的Mark Word信息

-

Class Metadata Address

存储指向对象存储类型的指针

-

Array Length

数组的长度

只有数组对象有该属性

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

锁状态

23 bits

2 bits

4 bits

1 bit

2 bits

无锁状态

identity hash code(首次调用)

分代年龄

0

01

偏向锁

Thread ID

epoch

分代年龄

1

01

轻量级锁

指向线程栈中Lock Record的指针

00

重量级锁

指向监视器(monitor)的指针

10

GC标记

0

11

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

锁状态

25 bits

31 bits

1 bit

4 bits

1 bit

2 bits

无锁状态

unused

identity hash code(首次调用)

unused

分代年龄

0

01

锁状态

54 bits

2 bits

1 bit

4 bits

1 bit

2 bits

偏向锁

Thread ID

epoch

unused

分代年龄

1

01

锁状态

62 bits

2 bits

轻量级锁

指向线程栈中Lock Record的指针

00

重量级锁

指向监视器(monitor)的指针

10

GC标记

0

11

由此可知,在无锁状态下,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知识整理

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/08/29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 参考博客:
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档