0

0

详解轻量级锁的自旋等待_通过CAS修改Mark Word指向栈帧记录

P粉602998670

P粉602998670

发布时间:2026-02-21 16:42:11

|

168人浏览过

|

来源于php中文网

原创

轻量级锁加锁时必须自旋而非挂起线程,因挂起/唤醒涉及用户态到内核态切换,开销远大于用户态空转几个cpu周期;jvm默认仅在多核环境下自旋,且自旋次数由自适应策略动态调整。

详解轻量级锁的自旋等待_通过cas修改mark word指向栈帧记录

轻量级锁加锁时为什么必须自旋而不是直接挂起线程

因为挂起/唤醒线程涉及用户态到内核态切换,开销远大于在用户态空转几个 CPU 周期。JVM 默认只允许 os::is_MP() 为 true 的场景下自旋(即多核),且自旋次数受 -XX:PreBlockSpin 控制(Java 6 后已废弃,实际由自适应策略接管)。

常见错误现象:Thread.State = BLOCKED 却发现竞争并不激烈——说明自旋未生效,可能因锁被其他线程长时间持有,或 JVM 认定当前线程不适合自旋(如已自旋失败过、CPU 负载高)。

  • 自旋不是无限的:JVM 会根据前一次获取锁的成功率动态调整,失败则降级为重量级锁
  • 自旋期间线程仍占用 CPU,若锁持有时间长,反而浪费资源
  • 单核 CPU 上默认禁用自旋,因为无法真正“并发”,只会白占调度时间

Mark Word 如何通过 CAS 指向帧中的 Lock Record

轻量级锁加锁本质是用 CAS 将对象头的 Mark Word 替换为指向当前线程栈中 Lock Record 的指针。这个指针不是任意地址,而是栈帧里一块固定结构的内存(包含原始 Mark Word 备份和对象头指针)。

关键点在于:CAS 必须成功,否则说明有竞争,进入自旋或膨胀流程。失败后不能重试无限次,否则导致 ABA 问题或饥饿。

  • Lock Record 在栈上分配,生命周期与方法调用一致;逃逸分析失败时可能被分配到堆,但此时轻量级锁通常已失效
  • CAS 修改的是对象头低 3 位为 00(表示轻量级锁状态),同时写入指向 Lock Record 的指针
  • 若 CAS 失败,说明 Mark Word 已被其他线程修改(比如已被锁、或正在膨胀),需检查是否为重入(对比线程 ID)

为什么重入时不新建 Lock Record 而是计数

重入时 JVM 会检查 Mark Word 中存储的线程 ID 是否与当前线程一致。一致则跳过 CAS,直接在栈帧已有 Lock Recorddisplaced_mark_word 区域叠加一个计数器(实际存于 Lock Record 后续字段,非 Mark Word 本身)。

Voicenotes
Voicenotes

Voicenotes是一款简单直观的多功能AI语音笔记工具

下载

这样做避免了重复分配栈空间,也防止多次 CAS 引发不必要的竞争。但要注意:计数器不存于对象头,而是在每个线程自己的栈帧里维护,所以跨线程不可见。

  • 计数器溢出(超过 0x3FFFFFFF)会导致锁膨胀,但现实中几乎不会发生
  • 解锁时按计数器倒序还原 Mark Word,最后一次才真正恢复原值
  • 若重入期间发生锁膨胀,计数器信息会丢失,后续解锁行为由重量级锁机制接管

自旋等待失败后锁膨胀的临界判断逻辑

膨胀不是一蹴而就的。当自旋一定轮次后仍未获得锁,JVM 会检查当前 Mark Word 状态:若仍是轻量级锁状态(即指向某线程栈帧),但该线程已阻塞或长时间未释放,则触发膨胀;若已是偏向锁状态,则先撤销再膨胀。

典型错误认知:认为“自旋失败=立刻膨胀”。实际上 JVM 会先尝试让出 CPU(os::NakedYield()),再检查是否需要升级。这中间可能穿插 GC、线程调度等干扰。

  • 膨胀时需将所有 Lock Record 中的备份 Mark Word 拷贝回对象头,并设置锁标志位为 10(重量级锁)
  • 原轻量级锁持有线程继续运行,但后续争抢者全部进入 ObjectMonitor 的 _EntryList 或 _WaitSet
  • 膨胀过程本身是同步的,由第一个检测到需膨胀的线程执行,其余线程等待其完成

真正容易被忽略的是:自旋策略和膨胀阈值完全由 JVM 运行时采集的统计信息驱动,没有硬编码阈值。同一段代码,在不同负载、不同 GC 阶段、不同 CPU 亲和性下,可能走完全不同的锁路径。别迷信 -XX:PreBlockSpin,它早就不起作用了。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

421

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

594

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

421

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

594

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

695

2023.08.10

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

94

2025.12.01

word背景色怎么改成白色
word背景色怎么改成白色

Word是微软公司的一个文字处理器软件。word为用户提供了专业而优雅的文档工具,帮助用户节省时间并得到优雅美观的结果。word提供了许多易于使用的文档创建工具,同时也提供了丰富的功能供创建复杂的文档使用。怎么word背景色怎么该呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

3734

2023.07.21

word最后一页空白页怎么删除
word最后一页空白页怎么删除

word最后一页空白页删除方法有:通过删除回车符、调整页边距、删除分节符或调整分页符位置,您可以轻松去除最后一页的空白页。根据您实际的文档情况,选择适合您的方法进行操作,使您的文档更加美观和整洁。本专题为大家提供word最后一页空白页怎么删除不了相关的各种文章、以及下载和课程。

331

2023.07.24

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

928

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1万人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号