Synchronized与Java对象头

https://mp.weixin.qq.com/s/2yxexZUr5MWdMZ02GCSwdA

1 synchronized实现原理

synchronized实现同步的基础是:Java中的每一个对象都可以作为锁。具体表现为以下3种形式:

  • 对于普通同步方法,锁是当前实例对象。
  • 对于静态同步方法,锁是当前类的Class对象。
  • 对于同步方法块,锁是Synchonized括号里配置的对象。

当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁。那么锁到底存在哪里呢?锁里面会存储什么信息呢?

从JVM规范中可以看到,synchronized获取和释放锁就是进入和退出Monitor对象,这个Monitor对象就是上面所说的作为锁的对象。通过Monitor对象来实现方法同步和代码块同步,但两者的实现细节不一样。代码块同步是使用monitorenter和monitorexit指令实现的,而方法同步是使用另外一种方式实现的,细节在JVM规范里并没有详细说明。但是,方法的同步同样可以使用这两个指令来实现。

2 Java对象头

由于Java面向对象的思想,在JVM中需要大量存储对象,存储时为了实现一些额外的功能,需要在对象中添加一些标记字段用于增强对象功能,这些标记字段组成了对象头。

在Java SE1.6之前,synchronized一直都是重量级锁,如果某个线程获得了锁,其它获取锁的线程必须阻塞。在高并发的情况下,会有大量线程阻塞,导致系统响应速度急剧下降;同时不断的获取和释放锁也会导致线程不断切换,给系统造成较大的负担。在Java SE1.6之后,为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁,以及锁的存储结构和升级过程。这些锁就存在锁对象的对象头中。

2.1 Java对象头的长度

如果对象是数组类型,则虚拟机用3个字宽(Word)存储对象头(1个字宽用来存储数组长度);如果对象是非数组类型,则用2字宽存储对象头。在32位虚拟机中,1字宽等于4字节,即32bit;在64位虚拟机下,1字宽等于64bit。如表所示:

长度内容说明
32/64bitMark Word存储对象的hashCode或锁信息等
32/64bitClass Metadata Address存储到对象类型数据的指针
32/64bitArray Length数组的长度(仅当当前对象为数组时存在)

2.2 Mark Word的存储结构

Java对象头中以一字宽的长度存储Mark Word,里面包含了对象的hashCode,分代年龄和锁标记位。

锁状态25bit4bit1bit是否是偏向锁2bit 锁标志位
无状态锁对象的hashcode对象分代年龄001

2.3 Mark Word的变化

运行期间,Mark Word的数据类型会随着锁标志位的改变而改变,一共有四种情况:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值