synchronized 锁的性能优化:自适应自旋、锁消除、锁粗化与偏向锁

在并发编程中,锁的机制至关重要。synchronized 作为 Java 中最基础的同步工具,长期以来被广泛使用。然而,synchronized 的性能问题也一直存在,尤其是在多线程高并发的场景下,频繁的加锁和解锁操作会带来不小的开销。为了解决这一问题,JDK 1.6 引入了多种优化技术,以提高 synchronized 锁的性能,降低系统开销。

本文将详细介绍 JDK 1.6 中对 synchronized 锁的优化,包括 自适应自旋锁锁消除锁粗化 以及 偏向锁、轻量级锁、重量级锁,帮助你理解这些技术背后的原理,并在实际开发中充分利用它们。

1. 自适应自旋锁:减少不必要的等待

自旋锁的概念

自旋锁是指线程在获取锁失败时,不进入阻塞状态,而是不断循环尝试获取锁。自旋的缺点在于如果自旋时间过长,可能会浪费大量 CPU 时间,导致性能下降。

自适应自旋锁优化

在 JDK 1.6 中,自适应自旋锁被引入来解决自旋时间过长的问题。自适应自旋锁会根据系统的负载、锁的竞争情况等多种因素动态调整自旋的次数和时间,避免了传统自旋锁的资源浪费。

  • 如果线程获得锁的成功率高,那么自旋时间短,能够尽快获得锁。
  • 如果线程获得锁的成功率低,自旋时间则较长,避免了长时间自旋带来的性能损耗。

通过自适应的自旋策略,JDK 1.6 使得自旋锁变得更聪明、更高效。

2. 锁消除:消除不必要的锁

锁消除的概念

锁消除是指在某些情况下,JVM 会分析并移除不必要的同步操作。例如,当 JVM 发现某些对象永远不会被多线程同时访问时,就可以消除对这些对象的锁,从而提高性能。

应用示例

例如,StringBuffer 类的 append 方法可能被 synchronized 修饰,但在某些情况下,StringBuffer 的对象仅在一个线程中使用。在这种情况下,JVM 可以消除无意义的 synchronized 锁,避免不必要的性能开销。

@Override
public synchronized StringBuffer append(Object obj) {toStringCache = null;super.append(String.valueOf(obj));return this;
}

通过 逃逸分析,如果 JVM 确定 StringBuffer 对象仅会在单线程中使用,它可以消除 synchronized 锁,因为单线程中的操作自然是线程安全的。

3. 锁粗化:减少无谓的加锁解锁

锁粗化的概念

锁粗化是指将多次加锁解锁的操作合并为一次大的加锁解锁操作。例如,如果一个对象在多个地方多次加锁,我们可以将这些锁合并为一个大范围的同步块,从而减少锁的申请与释放次数,提升性能。

应用示例

假设我们有如下代码:

public void lockCoarsening() {synchronized (this) {// do something}synchronized (this) {// do something else}synchronized (this) {// do another thing}
}

这段代码中,synchronized 被多次调用,但实际上每次加锁解锁的内容都非常短。如果将它们合并成一个大的同步块:

public void lockCoarsening() {synchronized (this) {// do something// do something else// do another thing}
}

通过锁粗化,减少了锁的申请和释放次数,显著提升了性能。锁粗化在没有竞争的情况下尤其有效,但在循环中不适用,因为可能导致线程长时间无法获得锁。

4. 偏向锁、轻量级锁、重量级锁:锁的多级演进

在 JDK 1.6 中,synchronized 锁的实现被优化为偏向锁、轻量级锁和重量级锁,这三种锁分别适用于不同的竞争情况。

4.1 偏向锁

偏向锁的思想是,如果某个锁长期没有竞争,那么该锁就不需要加锁,只需要打一个标记即可。当第一个线程获得锁时,锁会记录下该线程的信息,并允许后续的线程直接获取锁(如果是同一个线程)。

  • 性能最优:避免了加锁操作,极大地减少了同步开销。
  • 适用场景:适合没有线程竞争的情况。

4.2 轻量级锁

当有多个线程竞争一个偏向锁时,偏向锁会升级为轻量级锁。轻量级锁使用 CAS(比较和交换)操作来尝试获取锁,避免线程阻塞。

  • 性能较好:通过自旋和 CAS 操作避免了线程阻塞。
  • 适用场景:适合竞争较少、锁持有时间较短的场景。

4.3 重量级锁

当锁的竞争较为激烈,并且自旋和 CAS 无法有效解决时,轻量级锁会升级为重量级锁。重量级锁依赖操作系统的同步机制,涉及线程的阻塞和唤醒,因此开销较大。

  • 性能最差:涉及线程阻塞和上下文切换,性能开销较大。
  • 适用场景:适合长时间锁竞争的情况。

锁的升级路径

  • 无锁偏向锁轻量级锁重量级锁

5. 小结

JDK 1.6 在 synchronized 锁的基础上引入了多项优化,包括自适应自旋锁、锁消除、锁粗化和偏向锁、轻量级锁、重量级锁等。这些优化显著提高了并发程序的性能,特别是在多线程高并发的环境下。具体来说:

  • 自适应自旋锁:根据实际竞争情况动态调整自旋时间,避免不必要的性能开销。
  • 锁消除:通过逃逸分析消除不必要的锁,提高效率。
  • 锁粗化:减少无意义的锁申请和释放,提升执行效率。
  • 偏向锁、轻量级锁、重量级锁:通过不同的锁状态来适应不同的线程竞争情况,提高整体性能。

了解这些优化技术并合理运用,可以帮助开发者编写更加高效的并发程序,充分发挥 Java 并发性能的潜力。

🌟 关注我的CSDN博客,收获更多技术干货! 🌟

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【小白学机器学习34】用python进行基础的数据统计 mean,var,std,median,mode ,四分位数等

目录 1 用 numpy 快速求数组的各种统计量:mean, var, std 1.1 数据准备 1.2 直接用np的公式求解 1.3 注意问题 1.4 用print() 输出内容,显示效果 2 为了验证公式的后背,下面是详细的展开公式的求法 2.1 均值mean的详细 2.2 方差var的…

视频推拉流EasyDSS互联网直播点播平台技术特点及应用场景剖析

在数字科技日新月异的今天,视频直播和点播已经成为互联网内容传播的重要方式之一。而互联网直播点播平台EasyDSS作为功能强大的流媒体直播点播视频能力平台,提供了一站式的视频推拉流、转码、直播、点播、时移回放、存储等视频服务,广泛应用于…

【测试工具JMeter篇】JMeter性能测试入门级教程(一)出炉,测试君请各位收藏了!!!

一、前言 Apache JMeter是纯Java的开源软件,最初由Apache软件基金会的Stefano Mazzocchi开发,旨在加载测试功能行为和测量性能。可以使用JMeter进行性能测试,即针对重负载、多用户和并发流量测试Web应用程序。 我们选择JMeter原因 是否测试过…

ffmpeg视频滤镜:提取缩略图-framestep

滤镜描述 官网地址 > FFmpeg Filters Documentation 这个滤镜会间隔N帧抽取一帧图片&#xff0c;因此这个可以用于设置视频的缩略图。总体上这个滤镜比较简单。 滤镜使用 滤镜参数 framestep AVOptions:step <int> ..FV....... set frame st…

Spring源码(十三):Spring全系列总结

Spring总结篇,不同于之前抽丝剥茧式地纵向深入源码,本次从横向的角度出发,希望可以带个读者一个完全不同的Spring视角。 2024年重置版,搞点不一样的东西。希望通过本篇的内容,将之前的文章全部给串起来。 相关前文: Spring Boot启动加载Spring Web请求处理流程Spring上…

【AIGC】如何准确引导ChatGPT,实现精细化GPTs指令生成

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | 提示词Prompt应用实例 文章目录 &#x1f4af;前言&#x1f4af;准确引导ChatGPT创建爆款小红书文案GPTs指令案例&#x1f4af; 高效开发GPTs应用的核心原则明确应用场景和目标受众构建多样化风格模板提问与引…

电影风格城市夜景旅拍Lr调色教程,手机滤镜PS+Lightroom预设下载!

调色教程 电影风格城市夜景旅拍通过 Lightroom 调色&#xff0c;将城市夜晚的景色打造出如同电影画面般的质感和氛围。以独特的色彩和光影处理&#xff0c;展现出城市夜景的魅力与神秘。 预设信息 调色风格&#xff1a;电影风格预设适合类型&#xff1a;人像&#xff0c;街拍…

拥抱极简主义前端开发:NoCss.js 引领无 CSS 编程潮流

在前端开发的世界里&#xff0c;我们总是在不断追寻更高效、更简洁的方式来构建令人惊艳的用户界面。而今天&#xff0c;我要向大家隆重介绍一款具有创新性的工具 ——NoCss.js&#xff0c;它将彻底颠覆你对传统前端开发的认知&#xff0c;引领我们进入一个全新的无 CSS 编程时…

【JavaEE初阶】多线程初阶下部

文章目录 前言一、volatile关键字volatile 能保证内存可见性 二、wait 和 notify2.1 wait()方法2.2 notify()方法2.3 notifyAll()方法2.4 wait 和 sleep 的对比&#xff08;面试题&#xff09; 三、多线程案例单例模式 四、总结-保证线程安全的思路五、对比线程和进程总结 前言…

使用 前端技术 创建 QR 码生成器 API1

前言 QR码&#xff08;Quick Response Code&#xff09;是一种二维码&#xff0c;于1994年开发。它能快速存储和识别数据&#xff0c;包含黑白方块图案&#xff0c;常用于扫描获取信息。QR码具有高容错性和快速读取的优点&#xff0c;广泛应用于广告、支付、物流等领域。通过扫…

vxe-modal VxeUI 窗口组件弹窗多窗口模式

VxeUI 实现在 vue 中使用弹窗组件&#xff0c;弹窗多个窗口可叠加&#xff0c;实现多实例的窗口组件。 npm install vxe-pc-ui4.3.6// ...import VxeUI from vxe-pc-uiimport vxe-pc-ui/lib/style.css// ...createApp(App).use(VxeUI).mount(#app)// ...官网&#xff1a;https…

无人机探测:光电侦测核心技术算法详解!

核心技术 双光谱探测跟踪&#xff1a; 可见光成像技术&#xff1a;利用无人机表面反射的自然光或主动光源照射下的反射光&#xff0c;通过高灵敏度相机捕捉图像。该技术适用于日间晴朗天气下的无人机探测&#xff0c;具有直观、易于识别目标的特点。 红外成像技术&#xff1…

【ArcGISPro】Sentinel-2数据处理

错误 默认拉进去只组织了4个波段,但是实际有12个波段 解决方案 数据下载 Sentinel-2 数据下载-CSDN博客 数据处理 数据查看 创建镶嵌数据集 在数据管理工具箱中找到创建镶嵌数据集

现代密码学

概论 计算机安全的最核心三个关键目标&#xff08;指标&#xff09;/为&#xff1a;保密性 Confidentiality、完整性 Integrity、可用性 Availability &#xff0c;三者称为 CIA三元组 数据保密性&#xff1a;确保隐私或是秘密信息不向非授权者泄漏&#xff0c;也不被非授权者使…

Python绘制太极八卦

文章目录 系列目录写在前面技术需求1. 图形绘制库的支持2. 图形绘制功能3. 参数化设计4. 绘制控制5. 数据处理6. 用户界面 完整代码代码分析1. rset() 函数2. offset() 函数3. taiji() 函数4. bagua() 函数5. 绘制过程6. 技术亮点 写在后面 系列目录 序号直达链接爱心系列1Pyth…

uniapp vue2项目迁移vue3项目

uniapp vue2项目迁移vue3项目&#xff0c;必须适配的部分 一、main.js 创建应用实例 // 之前 - Vue 2 import Vue from vue import App from ./App Vue.config.productionTip false // vue3 不再需要 App.mpType app // vue3 不再需要 const app new Vue({ ...App }) …

卷积神经网络学习记录

目录 神经网络基础定义&#xff1a; 基本组成部分 工作流程 卷积层&#xff08;卷积定义&#xff09;【CONV】&#xff1a; 卷积层&#xff08;Convolutional Layer&#xff09; 特征提取&#xff1a;卷积层的主要作用是通过卷积核&#xff08;或滤波器&#xff09;运算提…

element-ui 中el-calendar 日历插件获取显示的第一天和最后一天【原创】

需要获取el-calendar 日历组件上的第1天和最后一天。可以通过document.querySelector()方法进行获取dom元素中的值&#xff0c;这样避免计算问题。 获取的过程中主要有两个难点&#xff0c;第1个是处理上1月和下1月的数据&#xff0c;第2个是跨年的数据。 直接贴代码&#xff…

一个高度可扩展的 Golang ORM 库【GORM】

GORM 是一个功能强大的 Golang 对象关系映射&#xff08;ORM&#xff09;库&#xff0c;它提供了简洁的接口和全面的功能&#xff0c;帮助开发者更方便地操作数据库。 1. 完整的 ORM 功能 • 支持常见的关系模型&#xff1a; • Has One&#xff08;一对一&#xff09; • …

【大数据学习 | Spark-Core】Spark的改变分区的算子

当分区由多变少时&#xff0c;不需要shuffle&#xff0c;也就是父RDD与子RDD之间是窄依赖。 当分区由少变多时&#xff0c;是需要shuffle的。 但极端情况下&#xff08;1000个分区变成1个分区)&#xff0c;这时如果将shuffle设置为false&#xff0c;父子RDD是窄依赖关系&…