一、前言
感觉什么都不会,从哪开始呀!
这是最近我总能被问到的问题,也确实是。一个初入编程职场的新人,或是一个想重新努力学习的老司机,这也不会,那也不会,总会犯愁从哪开始。
讲道理,毕竟 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 种组合00、01、10、11),所以无锁、偏向锁,前又占了一位偏向锁标记。最终:101 为无锁、001 为偏向锁。
1.2 验证对象结构
为了可以更加直观的看到对象结构,我们可以借助 openjdk 提供的 jol-core 进行打印分析。
引入 POM
<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-cli -->
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-cli</artifactId>
<version>0.14</version>
</dependency>
测试代码
深入解析Java的synchronized:对象头结构与锁升级

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

被折叠的 条评论
为什么被折叠?



