锁原理与对象头

对象头

对象头是堆中对象的头结构,它由两个部分组成,mark wordklass 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

线程学习记录-锁原理与对象头相关推荐

  1. UNIX再学习 -- 记录锁

    APUE第 3 章,参看:UNIX再学习 -- 文件I/O  fcntl 函数它的记录锁功能我们当时没讲.接下来就详细说明下. 一.读写冲突 1.如果两个或两个以上的进程同时向一个文件的某个特定的区域 ...

  2. java线程学习记录

    线程 什么是线程? 线程是一个轻量级的子进程,是最小的处理单元.多线程和多进程都用于实现多任务处理.但是,我们使用多线程而不是多进程,因为线程使用共享内存区域,它们不分配单独的内存区域以节省内存,而且 ...

  3. Asp.Net MVC学习记录之“一个实体对象不能由多个 IEntityChangeTracker 实例引用”

    前言 由于刚刚接触mvc不久,之前都是看一些教程学习的,所以一学会(只是皮毛)就非常兴奋的来做mvc的网站,结果做没多久就出现了一个错误 解决方案 当时度娘了找了好久都没找到有效的解决方案,也上了MS ...

  4. JavaScript学习记录 (三) 函数和对象

    1.函数 使用 function 关键字来声明函数 函数的命名规则和变量一样 JS没有函数签名,所以没有函数重载 JS函数中的所有参数都是值传递:不能通过引用传递 // 定义函数 function t ...

  5. Python 学习记录(1)对象命名导致的问题

    在我的demo中我尝试将字符串转换成datetime.datetime类型,如下所示 start_time =datetime.datetime.strptime('2010-2-4 07:30',& ...

  6. java的对象物理结构,以及对象头中MarkWord与锁的关系

    关于锁升级可参看 java synchronized原理与 为何锁升级及过程_toforu的博客-CSDN博客_为什么要锁升级 java 对象头 我们都知道,Java对象存储在堆(Heap)内存.那么 ...

  7. Java锁的逻辑(结合对象头和ObjectMonitor)

    我们都知道在Java编程中多线程的同步使用synchronized关键字来标识,那么这个关键字在JVM底层到底是如何实现的呢. 我们先来思考一下如果我们自己实现的一个锁该怎么做呢: 首先肯定要有个标记 ...

  8. java 偏向锁 重偏向_锁原理:偏向锁、轻量锁、重量锁

    java中每个对象都可作为锁,锁有四种级别,按照量级从轻到重分为:无锁.偏向锁.轻量级锁.重量级锁.每个对象一开始都是无锁的,随着线程间争夺锁,越激烈,锁的级别越高,并且锁只能升级不能降级. 一.ja ...

  9. Java面向对象编程(第2版)_学习记录

    <Java面向对象编程(第2版)> 孙卫琴 编著 文章目录 一.介绍 (一)平台与开发环境 (二)一些知识 (三)数组 二.类的生命周期 (一)类的加载 1. 加载 2. 连接 3. 初始 ...

  10. 【java并发编程艺术学习】(四)第二章 java并发机制的底层实现原理 学习记录(二) synchronized...

    章节介绍 本章节主要学习 Java SE 1.6 中为了减少获得锁 和 释放锁 时带来的性能消耗 而引入的偏向锁 和 轻量级锁,以及锁的存储结构 和 升级过程. synchronized实现同步的基础 ...

最新文章

  1. 第十六章 推荐系统-机器学习老师板书-斯坦福吴恩达教授
  2. Leetcode之Database篇
  3. Timer和TimerTask类 例子 .
  4. java判断当前时间距离第二天凌晨的秒数
  5. Java基础知识(一)
  6. 修改map.html,HTML map 标签 | 菜鸟教程
  7. 微信小程序之 Classify(商品属性分类)
  8. 为什么一个实例只有一个LGWR
  9. 17.基于scrapy-redis两种形式的分布式爬虫
  10. 超微主板升级BIOS
  11. 条码软件如何自定义设置条形码尺寸
  12. C#小知识之中英文转换、去空格
  13. 专业英语---短语篇
  14. Navicat导入xlsx文件提示无法打开文件
  15. 【学习笔记】斯坦福SCI写作课 Unit 1
  16. 真相了:大众创业葬送了多少人的前程?
  17. 公司股东该发工资吗?发多少?
  18. 顶尖os2x说明书_如何在OS X中创建安全说明
  19. 三菱PLC学习-比较指令CMP,ZCP
  20. 如何把华为ONU当成普通交换机用并且划分VLAN,型号(华为MA5626,MA5620)

热门文章

  1. 英特尔推出全新RRP物联网平台 计划为零售技术投资一亿美元
  2. 交换机二/三层转发原理
  3. 新的抗VEGF药物——阿柏西普ELISA 试剂盒相关研究
  4. Linux之open虚拟专业网安装部署
  5. Java,设计,功能权限和数据权限,用户、角色、权限和用户组
  6. 英语AquilariaCrassna奇楠沉香
  7. 74HC595级联电路编程篇(三)
  8. tcp rst 情况
  9. 计算机毕业设计基于ssm乒乓球裁判管理系统
  10. WinEdt10.3 激活