写点什么

☕【JVM 技术之旅】深入 JVM 原理分析 synchronized

发布于: 2021 年 05 月 26 日
☕【JVM 技术之旅】深入JVM原理分析synchronized

技术回顾

在此让我们回顾一下 Java 对象的内存结构,为什么要回顾内存结构?因为 synchronized 同步锁,采用的底层所机制的 monitor 就和内存对象有关系,所以我们先回顾一下 Java 内存结构

Java 对象内存结构

HotSpot 虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)


对象头(Object Header)

markWord(标记字段)

用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等等,这部分数据的长度在 32 位和 64 位的虚拟机(暂 不考虑开启压缩指针的场景)中分别为 32 个和 64 个 Bits


  • new 一个空对象在 32 为系统中占用内存大小是 8byte(对象头,在堆中)+4byte(对象的引用地址,在栈中)=12byte;

  • new 一个空对象在 64 为系统中占用内存大小是 16byte(对象头,在堆中)+8byte(对象的引用地址,在栈中)=24byte;如果开启了压缩指针机制 那么就是 8byte(对象头)+4byte 的链接指针+4byte(栈中的引用地址)。


Mark Word 被设计成一个非固定的数据结构以便在极小的空间内存储尽量多的信息,它会根据对象的状态复用自己的存储空间

无锁状
加锁状态


其中轻量级锁和偏向锁是 Java 6 对 synchronized 锁进行优化后新增加的,稍后我们会简要分析


  • 这里我们主要分析一下重量级锁也就是通常说 synchronized 的对象锁,锁标识位为 10其中指针指向的是 monitor 对象(也称为管程或监视器锁)的起始地址

  • 每个对象都存在着一个 monitor 与之关联,对象与其 monitor 之间的关系有存在多种实现方式,如 monitor 可以与对象一起创建销毁或当线程试图获取对象锁时自动生成,但当一个 monitor 被某个线程持有后,它便处于锁定状态

  • 在 Java 虚拟机(HotSpot)中,monitor 是由 ObjectMonitor 实现的,其主要数据结构如下(位于 HotSpot 虚拟机源码 ObjectMonitor.hpp 文件,C++实现的)


ObjectMonitor() {      _header       = NULL;      _count        = 0; //记录个数      _waiters      = 0,      _recursions   = 0;      _object       = NULL;      _owner        = NULL;      \_WaitSet      = NULL; //处于wait状态的线程,会被加入到\_WaitSet      _WaitSetLock  = 0 ;      _Responsible  = NULL ;      _succ         = NULL ;      _cxq          = NULL ;      FreeNext      = NULL ;      _EntryList    = NULL ; //处于等待锁block状态的线程,会被加入到该列表      _SpinFreq     = 0 ;      _SpinClock    = 0 ;      OwnerIsThread = 0 ;    }  
复制代码


ObjectMonitor 中有两个队列,WaitSet 和 EntryList,用来保存 ObjectWaiter 对象列表( 每个等待锁的线程都会被封装成 ObjectWaiter 对象),owner 指向持有 ObjectMonitor 对象的线程当多个线程同时访问一段同步代码时


  • 首先会进入 EntryList 集合,当线程获取到对象的 monitor 后进入 Owner 区域,并把 monitor 中的 owner 变量设置为当前线程同时 monitor 中的计数器 count 加 1。

  • 若线程调用 wait() 方法,将释放当前持有的 monitor,owner 变量恢复为 null,count 自减 1,同时该线程进入 WaitSet 集合中等待被唤醒

  • 若当前线程执行完毕也将释放 monitor(锁)并复位变量的值,以便其他线程进入获取 monitor(锁)



由此看来,monitor 对象存在于每个 Java 对象的对象头中(存储的指针的指向),synchronized 锁便是通过这种方式获取锁的,也是为什么 Java 中任意对象可以作为锁的原因,同时也是 notify/notifyAll/wait 等方法存在于顶级对象 Object 中的原因

发布于: 2021 年 05 月 26 日阅读数: 62
用户头像

我们始于迷惘,终于更高水平的迷惘。 2020.03.25 加入

🏆 【酷爱计算机技术、醉心开发编程、喜爱健身运动、热衷悬疑推理的”极客狂人“】 🏅 【Java技术领域,MySQL技术领域,APM全链路追踪技术及微服务、分布式方向的技术体系等】 🤝未来我们希望可以共同进步🤝

评论

发布
暂无评论
☕【JVM 技术之旅】深入JVM原理分析synchronized