栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

并发编程:java的对象头存储了那些信息?synchronized是怎么进行优化的

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

并发编程:java的对象头存储了那些信息?synchronized是怎么进行优化的

对象
  • 对象头
    • synchronized的锁状态优化
      • 无锁
      • 偏向锁
      • 轻量级锁
      • 轻量级锁升级为重量级锁的条件
  • 实例数据
  • 对齐填充(非必须)

对象头

    synchronized使用锁对象是存储在对象头里面的。对象头由MarkWord和Class MetaData Address组成。对象头占12个字节(byte)

    MarkWord包括哈希码,GC分代年龄,锁状态标志,线程持有的锁和线程的偏向ID。
    Class MetaData Address 存储对象的类型指针,该指针指向它的类元数据。

synchronized的锁状态优化 无锁

这个阶段在对象头的存储是001,1bit记录了偏向锁位,01是记录了无锁阶段。

偏向锁

偏向锁时JDK1.6之后引进的锁优化。在无锁竞争的条件下,一个线程通过一次CAS尝试将对象头中Thread ID设置为自己的线程号,偏向锁的标准就被设置为1,锁标志位为01,这时候,锁的状态就位偏向锁,该线程获取成功。之后改线程只要持有的id与对象头设置的id一致,那么就可以直接访问同步代码块。

轻量级锁

当有第二个线程访问到时,锁的状态就有偏向锁改为轻量级锁。因为偏向锁不会主动释放锁,因此以后线程1在获取锁时,只需要比较当前Thread id是否与java对象头设置的id是否一致。如果不一致,那么就意味着这个有多个线程在访问同步代码块。而偏向锁不会主动释放第一个线程的Thread id,而是看线程1 是否还存活 。如果没有存活,那么锁对象会被重置为无锁,其他线程抢占式来获取锁,采用CAS来将对象头的Thread id设置为自己的id。如果线程1还在存活,说明存在锁竞争。锁会被挂起,其他线程会通过自旋来不停的尝试获取锁,竞争的线程不会阻塞。如果通过一定数量的CAS操作还是获取失败,表示此时存在其他线程竞争锁(两条或两条以上的线程竞争同一个锁),则轻量级锁会膨胀成重量级锁。

当锁膨胀到轻量级锁或重量级锁时,对象头中62位bit都会用来存储锁记录的地址 ,这些分代年龄、hashcode都会存与锁记录空间。而锁记录空间是存在于当前线程的栈帧中 。锁的状态会改为00,轻量级锁。虚拟机会使用CAS操作尝试把mark word指向当前的锁记录地址。

轻量级锁升级为重量级锁的条件

当自旋超过一定的次数(10次),或者一个线程在持有锁,一个在自旋,又有第三个来访时(发生了多个线程竞争锁),轻量级锁升级为重量级锁。锁记录有01改为10。

实例数据

存放类的属性数据信息,包括父类的属性信息,如果是数组的实例部分还包括数组的长度,这部分内存按 4 字节对齐。

对齐填充(非必须)

没有特别作用,起到占位符作用,因为HotSpot规定任何对象大小必须是8字节整数倍

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/977972.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号