identityHashCode与偏向锁
hashCode
我们知道在Java中,一切对象都继承自java.lang.Object类。这个类中有一个可继承的方法叫hashCode()。它在Object类中的方法签名是这样的:
public native int hashCode();
可以看到,如果一个对象不覆盖这个方法,那它会继承Object类的实现,是一个native的方法。这个时候,它会根据对象的内存地址返回哈希值。
所以我们运行下面这段代码会输出false:
public class HashCodeDemo {
public static void main(String[] args) {
Object objectA = new Object();
Object objectB = new Object();
System.out.println(objectA.hashCode() == objectB.hashCode());
}
}
有些对象需要根据对象的字段的内容来计算hash值,比如字符串String。本文不介绍如何复写一个hashCode()方法,有兴趣的可以自己去学习一下。
因为复写了hashCode()方法,所以以下代码会输出true:
public class HashCodeDemo {
public static void main(String[] args) {
String s1 = yasin shaw;
String s2 = yasin shaw;
System.out.println(s1.hashCode() == s2.hashCode());
}
}
identityHashCode
那如果一个对象覆盖了hashCode方法,我们仍然想获得它的内存地址计算的Hash值,应该怎么办呢?
java.lang.System类提供了一个静态方法:
public static native int identityHashCode(Object x);
这里我们顺便涉及一下字符串的知识:
public class HashCodeDemo {
public static void main(String[] args) {
String s1 = yasin shaw;
String s2 = yasin shaw;
System.out.println(s1.hashCode() == s2.hashCode());
System.out.println(System.identityHashCode(s1) == System.identityHashCode(s2));
String s3 = new String(yasin shaw);
String s4 = new String(yasin shaw);
System.out.println(s3.hashCode() == s4.hashCode());
System.out.println(System.identityHashCode(s3) == System.identityHashCode(s4));
}
}
// 输出:
true
true
true
false
可以看到,s1, s2是在常量池里面的,所以它们的内存地址也会相等,所以调用identityHashCode方法会返回true。但s3, s4是在堆里面的,所以调用identityHashCode方法会返回false。
与偏向锁的关系?
通常情况下,我们称”以内存计算的HashCode的方式“为“identity hash code”。所以其实未覆盖Object类的hashCode()方法也被称为“identity hash code”。
一个类被加载的时候,hashCode是被存放在对象头里面的Mark Word里面的。在32位的JVM中,它会占25位;在64位的JVM中,它会占31位。
需要注意的是:这里说的hashCode仅仅指的是identity hash code。如果不是identity hash code,那它不会存储在对象头里。
每个Java对象都有对象头。如果是非数组类型,则用2个字宽来存储对象头,如果是数组,则会用3个字宽来存储对象头。在32位虚拟机中,一个字宽是32位;在64位虚拟机中,一个字宽是64位。对象头的内容如下表:
再来看看Mark Word的结构(无锁状态):
注意,这是“无锁状态”下。那如果有锁状态怎么办呢?我们知道,Java 6 以后,锁有三种,级别由低到高分别是:偏向锁、轻量级锁、重量级锁。
其中,轻量级锁和重量级锁都会在线程的栈里面创建一块专门的空间Displaced Mark Word,用于在获得锁的时候,复制“锁”的对象头里面的Mark Word内容,把当前的线程ID写进Mark Word;而在释放锁的时候,再从Displaced Mark Word复制回锁的Mark Word里面。
那偏向锁怎么办呢?
当一个对象已经计算过identity hash code,它就无法进入偏向锁状态;当一个对象当前正处于偏向锁状态,并且需要计算其identity hash code的话,则它的偏向锁会被撤销,并且锁会膨胀为重量级锁;
那什么时候对象会计算identity hash code呢?当然是当你调用未覆盖的Object.hashCode()方法或者System.identityHashCode(Object o)时候了。
identityHashCode与偏向锁的更多相关文章
- JVM锁简介:偏向锁、轻量级锁和重量级锁
转自:https://www.aimoon.site/blog/2018/05/21/biased-locking/ 比较复杂,简略见另一篇:https://www.cnblogs.com/twohe ...
- hashCode竟然不是根据对象内存地址生成的?还对内存泄漏与偏向锁有影响?
起因 起因是群里的一位童鞋突然问了这么问题: 如果重写 equals 不重写 hashcode 会有什么影响? 这个问题从上午10:45 开始陆续讨论,到下午15:39 接近尾声 (忽略这形同虚设的马 ...
- 难搞的偏向锁终于被 Java 移除了
背景 在 JDK1.5 之前,面对 Java 并发问题, synchronized 是一招鲜的解决方案: 普通同步方法,锁上当前实例对象 静态同步方法,锁上当前类 Class 对象 同步块,锁上括号里 ...
- Java线程并发中常见的锁--自旋锁 偏向锁
随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想 ...
- Java偏向锁实现原理(Biased Locking)
http://kenwublog.com/theory-of-java-biased-locking 阅读本文的读者,需要对Java轻量级锁有一定的了解,知道lock record, mark wor ...
- JVM中锁优化,偏向锁、自旋锁、锁消除、锁膨胀
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt364 本文将简单介绍HotSpot虚拟机中用到的锁优化技术. 自旋锁 互斥同 ...
- Synchronized锁性能优化偏向锁轻量级锁升级 多线程中篇(五)
不止一次的提到过,synchronized是Java内置的机制,是JVM层面的,而Lock则是接口,是JDK层面的 尽管最初synchronized的性能效率比较差,但是随着版本的升级,synchro ...
- 线程安全(中)--彻底搞懂synchronized(从偏向锁到重量级锁)
接触过线程安全的同学想必都使用过synchronized这个关键字,在java同步代码快中,synchronized的使用方式无非有两个: 通过对一个对象进行加锁来实现同步,如下面代码. synchr ...
- Java并发编程:Synchronized底层优化(偏向锁、轻量级锁)
Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...
随机推荐
- Python 有什么奇技淫巧?
知乎上有一个问题:Python 有什么奇技淫巧?其中有各种不按套路出牌的招数,也不乏一些惊为天人的"奇技淫巧",会让你大呼:居然还有这种操作??? 本文就是对日常使用过的或者觉得很 ...
- servlet实现多文件打包下载
当用户一次下载多个文件时.普通情况是,每下载一个文件,均要弹出一个下载的对话框.这给用户造成了非常大不便. 比較理想的情况是,用户选择多个文件后.server后端直接将多个文件打包为zip.以下贴出实 ...
- 009-mac下记事本工具 sublime text3
1.subline text3 下载:https://download.sublimetext.com/Sublime%20Text%20Build%203143.dmg 序列号:[来源与互联网,如有 ...
- 教你编译PHP7 (nginx+mysql+php7)
# 安装编译工具: yum install gcc automake autoconf libtool gcc-c++ # 安装基础库 yum install gd zlib zlib-devel o ...
- 哪个地图API 好用
之前我们能用的地图软件还寥寥无几,而且一个地图包动辄就上百M,还不支持GPS,没有实时路况,没有卫星图,一年也未必更新一次.现如今的地图功能已经极大丰富了,开发者的项目选择性也很大,地图哪个受众比较多 ...
- POJ - 2175 Evacuation Plan (最小费用流消圈)
题意:有N栋楼,每栋楼有\(val_i\)个人要避难,现在有M个避难所,每个避难所的容量为\(cap_i\),每个人从楼i到避难所j的话费是两者的曼哈顿距离.现在给出解决方案,问这个解决方案是否是花费 ...
- 论文笔记:IRGAN——A Minimax Game for Unifying Generative and Discriminative Information
2017 SIGIR 简单介绍 IRGAN将GAN用在信息检索(Information Retrieval)领域,通过GAN的思想将生成检索模型和判别检索模型统一起来,对于生成器采用了基于策略梯度的强 ...
- $Linux vi/vim编辑器常用命令与用法总结 (Markdown编辑版)
vi/vim是什么? Linux世界几乎所有的配置文件都是以纯文本形式存在的,而在所有的Linux发行版系统上都有vi编辑器,因此利用简单的文字编辑软件就能够轻松地修改系统的各种配置了,非常方便.vi ...
- iOS “弱账号” 暗转 “强账号”
一.背景 由于某些历史原因,我们产品中50%以上活跃用户是弱账户.即 客户端按照某种规则生成的一个伪id 存在keychain 里,作为这个用户的唯一标识,实现快速登录.正常情况下是不会有问题. 最近 ...
- iOS开发之UITableViewController重写
# UITablViewController方法的使用介绍 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // ...