大厂面试真题-说说synchronized的锁升级过程

在Java中,synchronized关键字是实现线程同步的一种方式,但其性能受到锁开销的影响。为了减少锁带来的性能损失,Java虚拟机(JVM)设计了一套锁升级机制。这一机制使得锁可以从无锁状态逐渐升级至重量级锁,以根据竞争程度动态调整锁策略,达到最佳性能平衡。以下是synchronized锁升级的详细过程:

一、无锁状态

  • 在对象创建之初,它处于无锁状态,没有任何锁标志位被设置。此时,对象可以被任何线程自由访问,因为没有线程试图获取锁。

二、偏向锁状态

  • 当第一个线程尝试获取synchronized锁时,JVM会将对象头标记为偏向锁状态,并在对象头中记录获取锁的线程ID。
  • 如果后续访问仍然是由这个线程发起的,它将无需进行额外的同步检查,即可直接访问对象,因为锁已经偏向于这个线程。这种优化减少了单一线程访问同一对象的开销。
  • 然而,如果其他线程尝试访问这个同步块,偏向锁将被撤销,并进入轻量级锁状态。撤销时会有一定的开销,包括检查偏向锁标识、CAS操作尝试清除偏向锁等。

三、轻量级锁状态

  • 当第二个线程尝试获取同一个对象的锁时,偏向锁会被撤销,对象变为轻量级锁状态。
  • 轻量级锁使用了ThreadLocal(此处指JVM内部为每个线程维护的锁记录,而非java.lang.ThreadLocal类)变量来存储锁记录,而不是直接使用操作系统的互斥锁。
  • 线程会在自己的栈帧中创建一个称为Lock Record的空间,用于存储锁的Mark Word的拷贝。然后通过CAS操作尝试将对象头的Mark Word替换为指向Lock Record的指针。
    • 如果成功,线程获得锁。
    • 如果失败,则说明存在竞争,线程将进入自旋状态,不断尝试CAS操作直到成功或达到自旋上限(JDK1.6前默认10次,之后采用自适应自旋,JVM自动调整)。
  • 自旋锁是线程在获取锁的过程中,不会去阻塞线程,而是通过循环获取锁。这避免了立即进入重量级锁状态,从而减少了线程阻塞和上下文切换的开销。但需要注意的是,如果自旋次数过多仍然没有获取到锁,会消耗较多的CPU资源。

四、重量级锁状态

  • 如果自旋超过一定次数(自旋阈值)仍未获得锁,轻量级锁将升级为重量级锁。
  • 重量级锁涉及操作系统层面的互斥锁(如Linux的mutex),可能导致线程阻塞和上下文切换,从而增加了性能开销。
  • 一旦升级为重量级锁,所有后续试图获取锁的线程都将被阻塞,直到锁被释放。被阻塞的线程会进入等待队列,而持有锁的线程执行完毕后,会唤醒队列中的下一个等待线程。

五、锁升级的特点

  • 锁升级的过程是不可逆的。一旦升级到重量级锁,就不会再降级回轻量级锁或偏向锁。
  • 锁升级是为了在不同的并发压力下优化锁的性能。在低竞争情况下,偏向锁和轻量级锁能够减少不必要的开销;而在高竞争情况下,重量级锁能够确保线程间的正确同步。

综上所述,synchronized的锁升级过程是一个从低开销到高开销、从非阻塞到阻塞的逐渐升级过程。这一机制旨在根据竞争程度动态调整锁策略,以达到最佳性能平衡。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/888213.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式硬件设计知识详解

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…

C语言初步介绍(初学者,大学生)【上】

1.C语⾔是什么? ⼈和⼈交流使⽤的是⾃然语⾔,如:汉语、英语、⽇语 那⼈和计算机是怎么交流的呢?使⽤ 计算机语⾔ 。 ⽬前已知已经有上千种计算机语⾔,⼈们是通过计算机语⾔写的程序,给计算机下达指令&am…

C#高级编程笔记--字符串和正则表达式

本章的主要内容如下: 创建字符串 格式化表达式 正则表达式​​​​​​​ 1.1 System.String类 System.String是一个类,专门用于存储字符串,允许对字符串进行许多操作。由于这种数据类型非常重要,C#提供了它自己…

‌图片编辑为底片,智能工具助力,创作精彩视觉作品

在当今数字化时代,图像编辑已成为表达创意和美化视觉作品的重要手段。借助智能工具,即使是初学者也能轻松驾驭图片编辑。接下为大家展示图片编辑为底片图片的效果。 1.打开“首助编辑高手”,选择这里“图片批量处理”版块页面上 2.导入保存有…

【AIGC产品经理】面试7家,拿到2个offer,薪资中上水平

Hello,大家好,我是一名不知名的5年B端金融产品经验的产品经理,成功转行AI产品经理,前期面试了北京百度、阿里、理想汽车、百川智能、华为、OPPO等多家大厂面试,但是由于已定居成都,主动终止了后续需要线下的…

uniapp 游戏 - 使用 uniapp 实现的扫雷游戏

0. 思路 1. 效果图 2. 游戏规则 扫雷的规则很简单。盘面上有许多方格,方格中随机分布着一些雷。你的目标是避开雷,打开其他所有格子。一个非雷格中的数字表示其相邻 8 格子中的雷数,你可以利用这个信息推导出安全格和雷的位置。你可以用右键在你认为是雷的地方插旗(称为标…

Web和UE5像素流送、通信教程

一、web端配置 首先打开Github地址:https://github.com/EpicGamesExt/PixelStreamingInfrastructure 找到自己虚幻引擎对应版本的项目并下载下来,我这里用的是5.3。 打开项目找到PixelStreamingInfrastructure-master > Frontend > implementat…

Docker系列-5种方案超详细讲解docker数据存储持久化(volume,bind mounts,NFS等)

文章目录 Docker的数据持久化是什么?1.数据卷(Data Volumes)使用Docker 创建数据卷创建数据卷创建一个容器,将数据卷挂载到容器中的 /data 目录。进入容器,查看数据卷内容停止并重新启动容器,数据卷中的数据…

Vue2电商项目(八) 完结撒花:图片懒加载、路由懒加载、打包的map文件

一、图片懒加载 安装:npm i vue-lazyload1.3 -s (弹幕建议按1.3版本) 引入 // 引入懒加载的图片 import hlw from /assets/hulu.jpg // 引入插件 import VueLazyload from vue-lazyload // 引入插件 Vue.use(VueLazyload, {// 懒加载默认的图…

【Linux-基础IO】磁盘的存储管理详解

磁盘的存储管理 由于一个磁盘中包含了大量的扇区,为了方便管理,我们对磁盘进行了分区,其中每个分区又进一步划分为多个块组(Block Group),每个块组中包含该块组的数据存储情况以及具体的数据 假设有一个8…

前端练习小项目 —— 让图片变得更 “色”

前言:相信读者在学习完了HTML、CSS和JavaScript之后已经想要迫不及待的想找一个小型的项目来练练手,那么这篇文章就正好能满足你的 “需求”。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 在开始学习…

SpringBoot基础(三):Logback日志

SpringBoot基础系列文章 SpringBoot基础(一):快速入门 SpringBoot基础(二):配置文件详解 SpringBoot基础(三):Logback日志 目录 一、日志依赖二、日志格式1、记录日志2、默认输出格式3、springboot默认日志配置 三、日志级别1、基础设置2、…

Linux中的网络指令:ping、netstat、watch、pidof、xargs

目录 Ping指令 netstat指令 watch指令 pidof指令 xargs指令 Ping指令 功能:检测两台主机间的网络连通性 语法:ping [选项] 目标主机的IP地址 (192.168.1.1)或域名(google.com) 常见选项&#xff1a…

P1010 [NOIP1998 普及组] 幂次方 Python题解

[NOIP1998 普及组] 幂次方 题目描述 任何一个正整数都可以用 2 2 2 的幂次方表示。例如 137 2 7 2 3 2 0 1372^7 2^3 2^0 137272320。 同时约定次方用括号来表示,即 a b a^b ab 可表示为 a ( b ) a(b) a(b)。 由此可知, 137 137 137 可表示…

华为 HCIP-Datacom H12-821 题库 (33)

🐣博客最下方微信公众号回复题库,领取题库和教学资源 🐤诚挚欢迎IT交流有兴趣的公众号回复交流群 🦘公众号会持续更新网络小知识😼 1.VLAN Pool 只要通过一个 SSID 就能够同时支持多个业务 VLAN,从而缩小广播域&#…

draw.io 设置默认字体及添加常用字体

需求描述 draw.io 是一个比较好的开源免费画图软件。但是其添加容器或者文本框时默认的字体是 Helvetica,一般的期刊、会议论文或者学位论文要求的英文字体是 Times New Roman,中文字体是 宋体,所以一般需要在文本字体选项里的下拉列表选择 …

Spring开发最佳实践之跨域处理

1. 跨域处理 1.1 异常现象 1.2 异常原因分析 跨源资源共享的官方定义如下: 跨源资源共享(CORS,Cross Origin Resource Sharing。或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自…

线性代数入门

线性代数入门 线性代数(Linear Algebra)是数学的重要分支之一,广泛应用于工程、计算机科学、物理学、经济学等领域。它主要研究向量、矩阵及其在空间中的变换。对于程序员来说,掌握线性代数的基础知识能够帮助更好地理解数据处理…

[C++]使用纯opencv部署yolov8-cls图像分类onnx模型

【算法介绍】 使用纯OpenCV部署YOLOv8-cls图像分类ONNX模型涉及几个关键步骤。 首先,你需要将YOLOv8-cls模型从PyTorch格式转换为ONNX格式,这是为了确保模型在不同深度学习框架之间的互操作性。这个转换过程通常是通过ultralytics框架中的model.export…

Linux TFTP服务器搭建

话得多说 先水一波字 TFTP(Trivial File Transfer Protocol)是一种简单的文件传输协议。它用于在计算机网络中传输文件,特别适用于在网络设备(如开发板和Linux系统下)代码调试等操作。TFTP使用UDP(User Da…