码农会锁,synchronized 对象头结构 (mark-word、Klass Pointer)、指针压缩、锁竞争,源码解毒、深度分析!

本文介绍了Java中的synchronized关键字,包括对象结构、锁升级过程和特性。通过分析HotSpot虚拟机的对象头结构,探讨了mark-word、Klass Pointer以及指针压缩,并通过实例验证了对象结构。synchronized提供了原子性、可见性和有序性保障,通过锁升级(无锁->偏向锁->轻量级锁->重量级锁)提高性能。文章还讨论了可重入性和锁降级的现象。
摘要由CSDN通过智能技术生成

一、前言

感觉什么都不会,从哪开始呀!

这是最近我总能被问到的问题,也确实是。一个初入编程职场的新人,或是一个想重新努力学习的老司机,这也不会,那也不会,总会犯愁从哪开始。

讲道理,毕竟 Java 涉及的知识太多了,要学应该是学会学习的能力,而不是去背题、背答案,拾人牙慧是不会有太多收益的。

学习的过程要找对方法,遇到问题时最好能自己想想,你有哪些方式学会这些知识。是不感觉即使让你去百度搜,你都不知道应该拿哪个关键字搜!只能拿着问题直接找人问,这样缺少思考,缺少大脑撞南墙的过程,其实最后也很难学会。

所以,你要学会的是自我学习的能力,之后是从哪开始都可以,重要的是开始和坚持!

二、面试题

谢飞机,小记,周末逛完奥特莱斯,回来就跑面试官家去了!

谢飞机:duang、duang、duang,我来了!

面试官:来的还挺准时,洗洗手吃饭吧!

谢飞机:嘿嘿...

面试官:你看我这块鱼豆腐,像不像 synchronized 锁!

谢飞机:啊!?

面试官:飞机,正好问你。synchronized、volatile,有什么区别呀?

谢飞机:嗯,volatile 保证可见性,synchronized 保证原子性!

面试官:那不用 volatile,只用 synchronized 修饰方式,能保证可见性吗?

谢飞机:这...,我没验证过!

面试官:吃吧,吃吧!一会给你个 synchronized 学习大纲,照着整理知识点!

三、synchronized 解毒

1. 对象结构

1.1 对象结构介绍

HotSpot 虚拟机 markOop.cpp 中的 C++ 代码注释片段,描述了 64bits 下 mark-word 的存储状态,也就是图 15-1 的结构示意。

这部分的源码注释如下:

64 bits:
--------
unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)
JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)
PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
size:64 ----------------------------------------------------->| (CMS free block)

unused:25 hash:31 -->| cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && normal object)
JavaThread*:54 epoch:2 cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && biased object)
narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)

源码地址jdk8/hotspot/file/vm/oops/markOop.hpp

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

  • mark-word:对象标记字段占 4 个字节,用于存储一些列的标记位,比如:哈希值、轻量级锁的标记位,偏向锁标记位、分代年龄等。

  • Klass Pointer:Class 对象的类型指针,Jdk1.8 默认开启指针压缩后为 4 字节,关闭指针压缩(-XX:-UseCompressedOops)后,长度为 8 字节。其指向的位置是对象对应的 Class 对象(其对应的元数据对象)的内存地址。

  • 对象实际数据:包括对象的所有成员变量,大小由各个成员变量决定,比如:byte 占 1 个字节 8 比特位、int 占 4 个字节 32 比特位。

  • 对齐:最后这段空间补全并非必须,仅仅为了起到占位符的作用。由于 HotSpot 虚拟机的内存管理系统要求对象起始地址必须是 8 字节的整数倍,所以对象头正好是 8 字节的倍数。因此当对象实例数据部分没有对齐的话,就需要通过对齐填充来补全。

另外,在 mark-word 锁类型标记中,无锁,偏向锁,轻量锁,重量锁,以及 GC 标记,5 种类中没法用 2 比特标记(2 比特最终有 4 种组合00011011),所以无锁、偏向锁,前又占了一位偏向锁标记。最终:101 为无锁、001 为偏向锁。

1.2 验证对象结构

为了可以更加直观的看到对象结构,我们可以借助 openjdk 提供的 jol-core 进行打印分析。

引入 POM

<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-cli -->
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值