线程学习记录-锁原理与对象头
锁原理与对象头
对象头
对象头是堆中对象的头结构,它由两个部分组成,mark word和klass word
mark word的简要介绍
mark word结构图示 如图所示:
- mark word的大小为64bit,在对象的5种状态中(无锁,偏向锁,轻量级锁,重量级锁,GC标记),mark word的结构有所不同
- 在 无锁 状态时,mark word的前56bit存储对象的hashcode信息。(前25bit为未使用,后31bit存储hashcode)。
- 在 偏向锁 状态时,mark word的前54bit存储获取锁的线程相关信息.
- 在 轻量级锁 状态时,mark word的前62bit存储线程的栈的指针。
- 在 重量级锁 状态时,markword的前62bit存储一个monitor对象信息。
klassword的简要介绍
- klassword 的32位或者64位代表元数据的指针。
- klassword的大小为64bit,如果开启了指针压缩,大小为32bit。
无锁态的对象,它的hashcode以及对象头信息
先上代码,这里我们使用了openjdk的jol包,可以看到对象以及jvm相关信息
<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.9</version></dependency>
public static void main(String[] args) throws InterruptedException {new JOLExample1().doHash();//jvm的信息// out.println(VM.current().details());}public void doHash(){Base a=new Base();out.println("before hash");out.println(ClassLayout.parseInstance(a).toPrintable());out.println("jvm----------"+Integer.toHexString(a.hashCode()));out.println("after hash");out.println(ClassLayout.parseInstance(a).toPrintable());}
打印的无锁对象信息为
由于本机cpu采用小端模式,所以看到的hashcode在对象头中的存储顺序是高低位相反的。
延迟偏向锁以及偏向锁和轻量级锁的性能差异分析
如果一个锁不存在线程竞争,那么它是一个偏向锁。但是不同版本jdk,存在偏向锁延迟策略,所以不同版本jdk的偏向锁机制有所差异。
经测试,jdk8默认有4秒偏向延迟。jdk13默认关闭了偏向延迟,直接使用偏向锁。
我们通过代码分析下,对象在不同阶段的锁类型以及对应的运行时间。
public class CompareLock {static Base base=new Base();public static void main(String[] args) throws InterruptedException {out.println("before lock");out.println(ClassLayout.parseInstance(base).toPrintable());TimeUnit.SECONDS.sleep(1);testSpeed();out.println("after lock");out.println(ClassLayout.parseInstance(base).toPrintable());}public static void testSpeed() {long stard = System.currentTimeMillis();for (int i = 0; i < 100000000; i++) {synchronized (base) {if (i==0){err.println("start locking 0");out.println(ClassLayout.parseInstance(base).toPrintable());}if (i==200000){err.println(" locking 200000");out.println(ClassLayout.parseInstance(base).toPrintable());}if (i==450000){err.println(" locking 450000");out.println(ClassLayout.parseInstance(base).toPrintable());}if (i==650000){err.println("locking 650000");out.println(ClassLayout.parseInstance(base).toPrintable());}}}long end = System.currentTimeMillis();long time = end - stard;out.println("time:==============================================" + time);}
}
下面是默认启动jvm,开启偏向延迟的情况,锁对象的状态变化为 无锁-轻量级锁-重量级锁(存疑,不知道为什么会变成重量锁,有了解的朋友可以回答下,执行时间1752ms
before lock
com.baiyu.bingfa.luban.jol.Base object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes totalstart locking 0
com.baiyu.bingfa.luban.jol.Base object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 10 f2 ad 02 (00010000 11110010 10101101 00000010) (44954128)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes totallocking 200000
com.baiyu.bingfa.luban.jol.Base object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 60 f2 ad 02 (01100000 11110010 10101101 00000010) (44954208)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes totallocking 450000
com.baiyu.bingfa.luban.jol.Base object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 2a 1d e7 17 (00101010 00011101 11100111 00010111) (401022250)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes totallocking 650000
com.baiyu.bingfa.luban.jol.Base object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 2a 1d e7 17 (00101010 00011101 11100111 00010111) (401022250)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes totaltime:==============================================1752
after lock
com.baiyu.bingfa.luban.jol.Base object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 2a 1d e7 17 (00101010 00011101 11100111 00010111) (401022250)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
下面是通过命令
-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0
取消偏向延迟的情况,此时直接进入偏向锁,锁对象的状态变化为 偏向锁-偏向锁-重量级锁(存疑,不知道为什么会变成重量锁,有了解的朋友可以回答下),执行时间1145ms
-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0
before lock
com.baiyu.bingfa.luban.jol.Base object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 05 00 00 00 (00000101 00000000 00000000 00000000) (5)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes totalstart locking 0
com.baiyu.bingfa.luban.jol.Base object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 05 38 3b 03 (00000101 00111000 00111011 00000011) (54212613)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes totallocking 200000
com.baiyu.bingfa.luban.jol.Base object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 05 38 3b 03 (00000101 00111000 00111011 00000011) (54212613)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes totallocking 450000
com.baiyu.bingfa.luban.jol.Base object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) ca 56 5a 18 (11001010 01010110 01011010 00011000) (408573642)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes totallocking 650000
com.baiyu.bingfa.luban.jol.Base object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) ca 56 5a 18 (11001010 01010110 01011010 00011000) (408573642)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes totaltime:==============================================1145
after lock
com.baiyu.bingfa.luban.jol.Base object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) ca 56 5a 18 (11001010 01010110 01011010 00011000) (408573642)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
注意,如果一个对象调用过hashcode方法,就不会成为偏向锁,可以在偏向锁之前计算hashcode,再打印对象头测试。
所以偏向锁状态无法保存对象hashcode,其他锁状态都有各自的存储hashcode方法(无锁对象头,轻量级锁线程栈指针,重量级锁monitor对象)
如果调用锁对象的wait方法,会立刻变成重量级锁。
public class CompareLock1 {static Base base=new Base();public static void main(String[] args) throws InterruptedException {out.println("before lock");out.println(ClassLayout.parseInstance(base).toPrintable());TimeUnit.SECONDS.sleep(1);new Thread(CompareLock1::testSpeed).start();TimeUnit.SECONDS.sleep(2);out.println("============================================");synchronized (base){base.notifyAll();}TimeUnit.SECONDS.sleep(2);out.println("============================================");out.println("after lock");out.println(ClassLayout.parseInstance(base).toPrintable());}public static void testSpeed() {synchronized (base){out.println("before wait");out.println(ClassLayout.parseInstance(base).toPrintable());try {base.wait();} catch (InterruptedException e) {e.printStackTrace();}out.println("after wait");out.println(ClassLayout.parseInstance(base).toPrintable());}}
}
执行结果:
before lock
# WARNING: Unable to get Instrumentation. Dynamic Attach failed. You may add this JAR as -javaagent manually, or supply -Djdk.attach.allowAttachSelf
# WARNING: Unable to attach Serviceability Agent. sun.jvm.hotspot.memory.Universe.getNarrowOopBase()
com.baiyu.bingfa.luban.jol.Base object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 05 00 00 00 (00000101 00000000 00000000 00000000) (5)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 4a 48 17 00 (01001010 01001000 00010111 00000000) (1525834)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes totalbefore wait
com.baiyu.bingfa.luban.jol.Base object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 05 48 ef 86 (00000101 01001000 11101111 10000110) (-2031138811)4 4 (object header) be 02 00 00 (10111110 00000010 00000000 00000000) (702)8 4 (object header) 4a 48 17 00 (01001010 01001000 00010111 00000000) (1525834)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total============================================
after wait
com.baiyu.bingfa.luban.jol.Base object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 02 b4 08 86 (00000010 10110100 00001000 10000110) (-2046249982)4 4 (object header) be 02 00 00 (10111110 00000010 00000000 00000000) (702)8 4 (object header) 4a 48 17 00 (01001010 01001000 00010111 00000000) (1525834)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total============================================
after lock
com.baiyu.bingfa.luban.jol.Base object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 4a 48 17 00 (01001010 01001000 00010111 00000000) (1525834)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
线程学习记录-锁原理与对象头相关推荐
- UNIX再学习 -- 记录锁
APUE第 3 章,参看:UNIX再学习 -- 文件I/O fcntl 函数它的记录锁功能我们当时没讲.接下来就详细说明下. 一.读写冲突 1.如果两个或两个以上的进程同时向一个文件的某个特定的区域 ...
- java线程学习记录
线程 什么是线程? 线程是一个轻量级的子进程,是最小的处理单元.多线程和多进程都用于实现多任务处理.但是,我们使用多线程而不是多进程,因为线程使用共享内存区域,它们不分配单独的内存区域以节省内存,而且 ...
- Asp.Net MVC学习记录之“一个实体对象不能由多个 IEntityChangeTracker 实例引用”
前言 由于刚刚接触mvc不久,之前都是看一些教程学习的,所以一学会(只是皮毛)就非常兴奋的来做mvc的网站,结果做没多久就出现了一个错误 解决方案 当时度娘了找了好久都没找到有效的解决方案,也上了MS ...
- JavaScript学习记录 (三) 函数和对象
1.函数 使用 function 关键字来声明函数 函数的命名规则和变量一样 JS没有函数签名,所以没有函数重载 JS函数中的所有参数都是值传递:不能通过引用传递 // 定义函数 function t ...
- Python 学习记录(1)对象命名导致的问题
在我的demo中我尝试将字符串转换成datetime.datetime类型,如下所示 start_time =datetime.datetime.strptime('2010-2-4 07:30',& ...
- java的对象物理结构,以及对象头中MarkWord与锁的关系
关于锁升级可参看 java synchronized原理与 为何锁升级及过程_toforu的博客-CSDN博客_为什么要锁升级 java 对象头 我们都知道,Java对象存储在堆(Heap)内存.那么 ...
- Java锁的逻辑(结合对象头和ObjectMonitor)
我们都知道在Java编程中多线程的同步使用synchronized关键字来标识,那么这个关键字在JVM底层到底是如何实现的呢. 我们先来思考一下如果我们自己实现的一个锁该怎么做呢: 首先肯定要有个标记 ...
- java 偏向锁 重偏向_锁原理:偏向锁、轻量锁、重量锁
java中每个对象都可作为锁,锁有四种级别,按照量级从轻到重分为:无锁.偏向锁.轻量级锁.重量级锁.每个对象一开始都是无锁的,随着线程间争夺锁,越激烈,锁的级别越高,并且锁只能升级不能降级. 一.ja ...
- Java面向对象编程(第2版)_学习记录
<Java面向对象编程(第2版)> 孙卫琴 编著 文章目录 一.介绍 (一)平台与开发环境 (二)一些知识 (三)数组 二.类的生命周期 (一)类的加载 1. 加载 2. 连接 3. 初始 ...
- 【java并发编程艺术学习】(四)第二章 java并发机制的底层实现原理 学习记录(二) synchronized...
章节介绍 本章节主要学习 Java SE 1.6 中为了减少获得锁 和 释放锁 时带来的性能消耗 而引入的偏向锁 和 轻量级锁,以及锁的存储结构 和 升级过程. synchronized实现同步的基础 ...
最新文章
- 第十六章 推荐系统-机器学习老师板书-斯坦福吴恩达教授
- Leetcode之Database篇
- Timer和TimerTask类 例子 .
- java判断当前时间距离第二天凌晨的秒数
- Java基础知识(一)
- 修改map.html,HTML map 标签 | 菜鸟教程
- 微信小程序之 Classify(商品属性分类)
- 为什么一个实例只有一个LGWR
- 17.基于scrapy-redis两种形式的分布式爬虫
- 超微主板升级BIOS
- 条码软件如何自定义设置条形码尺寸
- C#小知识之中英文转换、去空格
- 专业英语---短语篇
- Navicat导入xlsx文件提示无法打开文件
- 【学习笔记】斯坦福SCI写作课 Unit 1
- 真相了:大众创业葬送了多少人的前程?
- 公司股东该发工资吗?发多少?
- 顶尖os2x说明书_如何在OS X中创建安全说明
- 三菱PLC学习-比较指令CMP,ZCP
- 如何把华为ONU当成普通交换机用并且划分VLAN,型号(华为MA5626,MA5620)