当前位置: 首页 > news >正文

在 JDK 17 上完整观察 synchronized 锁升级过

在 JDK 17 上完整观察 synchronized 锁升级过在 JDK 17 上完整观察 synchronized 锁升级过

1、锁升级流程图解

在这里插入图片描述

2、代码实现

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;
import sun.misc.Unsafe;import java.lang.reflect.Field;
import java.util.concurrent.CountDownLatch;public class SupermarketLockDemo {private static final Unsafe UNSAFE = getUnsafe();// 共享锁对象static final Object lock = new Object();static final CountDownLatch latch = new CountDownLatch(10);private static Unsafe getUnsafe() {try {Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");theUnsafe.setAccessible(true);return (Unsafe) theUnsafe.get(null);} catch (Exception e) {throw new RuntimeException("无法获取Unsafe实例", e);}}public static void main(String[] args) throws Exception {System.out.println("=== JDK 17 锁升级演示(完全可靠版) ===");System.out.println("JVM详情: " + VM.current().details());// 1. 初始无锁状态 (001)System.out.println("\n=== 阶段1: 初始无锁状态 ===");printLockState(lock);// 2. 主线程首次获取锁 (偏向锁)synchronized (lock) {System.out.println("\n=== 阶段2: 主线程偏向锁 ===");printLockState(lock);}// 3. 轻量级锁演示Thread lightThread = new Thread(() -> {synchronized (lock) {System.out.println("\n=== 阶段3: 线程1轻量级锁 ===");printLockState(lock);}});lightThread.start();lightThread.join();// 4. 重量级锁演示System.out.println("\n=== 阶段4: 重量级锁触发 ===");for (int i = 0; i < 10; i++) {new Thread(() -> {synchronized (lock) {// 第一个获得锁的线程打印if (latch.getCount() == 10) {System.out.println("\n=== 阶段4: 重量级锁状态 ===");printLockState(lock);}latch.countDown();try { Thread.sleep(100); } catch (Exception e) {}}}).start();}latch.await();System.out.println("\n演示完成");}// 直接使用Unsafe获取对象头信息private static void printLockState(Object obj) {// 打印JOL布局System.out.println(ClassLayout.parseInstance(obj).toPrintable());try {// 获取对象地址long address = VM.current().addressOf(obj);// 读取对象头(Mark Word)long markWord = UNSAFE.getLong(obj, 0L);// 提取最后3位锁状态int lockBits = (int)(markWord & 0b111);System.out.println("对象内存地址: 0x" + Long.toHexString(address));System.out.println("Mark Word值: 0x" + Long.toHexString(markWord));System.out.println("锁状态位: " + padBinary(lockBits, 3));System.out.println("状态说明: " + getLockStateName(lockBits));} catch (Exception e) {System.err.println("解析错误: " + e.getMessage());// 尝试从JOL输出中提取锁状态String layout = ClassLayout.parseInstance(obj).toPrintable();parseLockStateFromString(layout);}}// 从字符串解析锁状态作为后备方案private static void parseLockStateFromString(String layout) {try {// 查找包含"(object header: mark)"的行for (String line : layout.split("\n")) {if (line.contains("(object header: mark)")) {// 提取十六进制部分String hexPart = line.split("0x")[1].split("\\)")[0].trim();// 解析十六进制字符串long markWord = Long.parseLong(hexPart, 16);// 提取最后3位锁状态int lockBits = (int)(markWord & 0b111);System.out.println("从字符串解析的锁状态: " + padBinary(lockBits, 3));System.out.println("状态说明: " + getLockStateName(lockBits));return;}}System.out.println("⚠️ 警告: 未能解析锁状态");} catch (Exception e) {System.err.println("字符串解析失败: " + e.getMessage());}}// 补全二进制位数private static String padBinary(int value, int bits) {return String.format("%" + bits + "s", Integer.toBinaryString(value)).replace(' ', '0');}private static String getLockStateName(int lockBits) {switch (lockBits) {case 0b001: return "无锁 (001)";case 0b101: return "偏向锁 (101)";case 0b000: return "轻量级锁 (000)";case 0b010: return "重量级锁 (010)";case 0b011: return "GC标记 (011)";default: return "未知状态 (" + padBinary(lockBits, 3) + ")";}}
}
D:\application\java17\bin\java.exe -Dcool.request.port=49369 "-javaagent:D:\application\idea\IntelliJ IDEA 2022.3.3\lib\idea_rt.jar=50258:D:\application\idea\IntelliJ IDEA 2022.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\workplace\gitcode\java-basic\target\classes;C:\Users\浩宸\.m2\repository\org\openjdk\jol\jol-core\0.17\jol-core-0.17.jar;C:\Users\浩宸\.config\.cool-request\request\lib\spring-invoke-starter.jar SupermarketLockDemo -XX:+UnlockDiagnosticVMOptions -XX:+PrintBiasedLockingStatistics -XX:BiasedLockingStartupDelay=0 -XX:+UseBiasedLocking --add-opens java.base/jdk.internal.vm=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.misc=ALL-UNNAMED
=== JDK 17 锁升级演示(完全可靠版) ===
# WARNING: Unable to get Instrumentation. Dynamic Attach failed. You may add this JAR as -javaagent manually, or supply -Djdk.attach.allowAttachSelf
JVM详情: # VM mode: 64 bits
# Compressed references (oops): 3-bit shift
# Compressed class pointers: 0-bit shift and 0x800000000 base
# Object alignment: 8 bytes
#                       ref, bool, byte, char, shrt,  int,  flt,  lng,  dbl
# Field sizes:            4,    1,    1,    2,    2,    4,    4,    8,    8
# Array element sizes:    4,    1,    1,    2,    2,    4,    4,    8,    8
# Array base offsets:    16,   16,   16,   16,   16,   16,   16,   16,   16=== 阶段1: 初始无锁状态 ===
java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)8   4        (object header: class)    0x00000d5812   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total对象内存地址: 0x7194ff310
Mark Word值: 0x1
锁状态位: 001
状态说明: 无锁 (001)=== 阶段2: 主线程偏向锁 ===
java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE0   8        (object header: mark)     0x0000009c4a9ff448 (thin lock: 0x0000009c4a9ff448)8   4        (object header: class)    0x00000d5812   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total对象内存地址: 0x7194ff310
Mark Word值: 0x9c4a9ff448
锁状态位: 000
状态说明: 轻量级锁 (000)=== 阶段3: 线程1轻量级锁 ===
java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE0   8        (object header: mark)     0x0000009c4bbff5d0 (thin lock: 0x0000009c4bbff5d0)8   4        (object header: class)    0x00000d5812   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total对象内存地址: 0x7194ff310
Mark Word值: 0x9c4bbff5d0
锁状态位: 000
状态说明: 轻量级锁 (000)=== 阶段4: 重量级锁触发 ====== 阶段4: 重量级锁状态 ===
java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE0   8        (object header: mark)     0x000001ea48a48cb2 (fat lock: 0x000001ea48a48cb2)8   4        (object header: class)    0x00000d5812   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total对象内存地址: 0x7194ff310
Mark Word值: 0x1ea48a48cb2
锁状态位: 010
状态说明: 重量级锁 (010)演示完成Process finished with exit code 0

3、各阶段解析说明

  • 无锁状态 (001)

对象头初始值: 0x0000000000000001
最后三位: 001 (二进制)
特点: 对象刚创建,未被任何线程使用

  • 偏向锁状态 (101)

对象头值: 0x0000000000000005
最后三位: 101 (二进制)
特点: 存储了主线程ID,后续该线程可直接使用

  • 轻量级锁状态 (000)

对象头值: 0x0000006a930ff610
最后三位: 000 (二进制)
JOL标识为 (thin lock),表示轻量级锁
特点: 指向线程栈中的锁记录

  • 重量级锁状态 (010)

对象头值: 0x0000028e9d00b20a
最后三位: 010 (二进制)
JOL标识为 (fat lock),表示重量级锁
特点: 指向操作系统层面的Monitor对象

http://www.dtcms.com/a/324341.html

相关文章:

  • 嵌入式第二十四课!!linux应用软件编程与文件操作!!!
  • Java 基础编程案例:斐波拉契数与从输入交互到逻辑处理
  • NodeJs学习日志(4):路由合并_环境配置_常用文件目录
  • HarmonyOS之module.json5功能详解
  • AI测试助手如何让Bug无处可藏
  • 湖南(源点咨询)市场调研 如何在行业研究中快速有效介入 中篇
  • 深入浅出DBSCAN:基于密度的聚类算法详解与Python实战
  • github上传文件
  • Navicat 无限适用
  • Tesseract训练个人字库操提高准确率操作全流程(详细)
  • 新手向:Python制作简易音乐播放器
  • Python中的 __name__
  • 遇到前端导出 Excel 文件出现乱码或文件损坏的问题
  • 异或循环冗余
  • Python设计模式 - 装饰模式
  • 新手向:Python实现文件加密解密工具
  • 旅行者1号无线电工作频段
  • 18.3 全量微调:数据预处理之清洗与准备
  • 机器学习——DBSCAN 聚类算法 + 标准化
  • 实现两个开发板的串口通讯(基于STC8实现)
  • 复刻苏宁易购(移动端)
  • 【GPT入门】第44课 检查 LlamaFactory微调Llama3的效果
  • cursor, vscode黄色波浪线警告问题
  • React:useEffect 与副作用
  • 小巧实用的工具——ZoomIt
  • 【C++对象诞生全解析】构造函数:从内存布局到高效初始化的终极指南
  • 152-基于CWT-CNN-BiGRU-Attention-SABO-LSSVM对滚动轴承的故障诊断
  • spring-boot-starter-data-redis 与 org.redisson 区别 联系
  • 【递归、搜索与回溯算法】深度优先搜索
  • Text2SQL 自助式数据报表开发(Chat BI)