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 并发编程 ...
随机推荐
- Eclipse集成SVN
安装Subversion1.82(SVN)插件 简介 :SVN是团队开发的代码管理工具,它使我们得以进行多人在同一平台之下的团队开发. 解决问题:Eclipse下的的SVN插件安装. 学到 ...
- (0.2.4)Mysql安装——yum源安装
转自:https://www.cnblogs.com/jimboi/p/6405560.html Centos6.8通过yum安装mysql5.7 1.下载好对应版本的yum源文件 2.安装用来配置m ...
- undefined reference to _imp__xmlFree
Re: [xml] MSYS and MINGW: undefined reference to _imp__xmlFree From: Mike Peat <mpeat unicorninte ...
- Android 按钮 弹出对话框
ackage com.example.helloworld; import android.os.Bundle;import android.app.Activity;import android.a ...
- SQL Server扩展属性的增、删、改、查
使用 sql 语句创建表时,可以使用系统存储过程 sp_addextendedproperty 给字段添加描述说明. sp_addextendedproperty 语法: sp_addextended ...
- 150. Evaluate Reverse Polish Notation(逆波兰表达式)
Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, ...
- openocd shell脚本
openocd.sh #! /usr/bin/expectset timeout 30spawn suexpect "密码:"send "123456\r"se ...
- Problem A. Array Factory XVII Open Cup named after E.V. Pankratiev Stage 4: Grand Prix of SPb, Sunday, Octorber 9, 2016
思路: 直接二分长度不可行,因为有负数. 考虑枚举坐便删l个数,那如果可以在短时间内求出符合条件的右边最小删的数的个数,这题便可做了. 即:当左边删l个数时,要使sum[n]-sum[l]-fsum[ ...
- 浅谈WLAN干扰与抗干扰技术
一. 无线干扰的分类和来源 无线干扰按照类型可划分为WLAN干扰和非WLAN干扰.WLAN干扰是指干扰源发送的RF信号也符合802.11标准,除此之外都是非WLAN干扰.对WLAN干扰,可进一步按照频 ...
- HDU2189 来生一起走
好久没发博客了,最近遇到以下奇葩错误,不明觉厉,忍不住发一篇 /*母函数,因为要求的是素数,那么先打一个素数表,所有的因子都是素数构成 但是遇到一个奇葩事,当num初值取1,结果就出不来,运行了好久 ...