Synchronized关键字的深入分析

一、引言

在多线程编程中,正确地管理并发是确保程序正确运行的关键。Java提供了多种同步工具,其中synchronized关键字是最基本且最常用的同步机制之一。本文旨在深入解析synchronized的实现原理,探讨其在不同应用场景中的使用,并通过示例让读者更好地理解其工作机制。

二、Synchronized基本概念

2.1 定义和作用

synchronized关键字可以用来修饰方法或者代码块。在方法或代码块被执行时,它能够保证同一时刻只有一个线程执行该段代码。这一特性使得synchronized成为实现临界区(Critical Section)和避免竞态条件(Race Condition)的简便方法。

2.2 使用方法

  • 同步实例方法:锁定当前实例对象
public synchronized void method() {
    // 同步代码
}

  • 同步静态方法:锁定当前类的Class对象。
public static synchronized void staticMethod() {
    // 同步代码
}

  • 同步代码块:指定一个特定对象作为锁。
public void method() {
    synchronized(this) {
        // 同步代码
    }
}

2.3 对比其他关键字

volatilefinal相比,synchronized不仅能保证可见性和顺序性,还能保证原子性。volatile仅保证变量的修改可见性和禁止指令重排序,而final关键字则用于声明常量。

三、Synchronized的内部机制

3.1 Java内存模型(JMM)

JMM处理了变量的可见性、原子性问题,为开发者屏蔽了不同CPU的复杂性。它确保一个线程对共享变量的修改,能够被其他线程看到,是通过内存屏障实现的。

3.2 锁的状态

在 JDK 6 中虚拟机团队对锁进行了重要改进,优化了其性能引入了 偏向锁、轻量级锁、适应性自旋、锁消除、锁粗化等实现,其中 锁消除和锁粗化本文不做详细讨论其余内容我们将对其进行逐一探究。

总体上来说锁状态升级流程如下:
在这里插入图片描述

  • 无锁状态
  • 偏向锁:假定锁不会存在竞争,避免了大多数情况下的同步。
  • 轻量级锁:当锁是偏向锁时,被另一个线程访问,会升级为轻量级锁。
  • 重量级锁:多线程竞争激烈时,轻量级锁会升级为重量级锁。

3.3 各种锁的获取流程

偏向锁
流程

当线程访问同步块并获取锁时处理流程如下:

  • 检查 mark word 的线程 id 。
  • 如果为空则设置 CAS 替换当前线程 id。如果替换成功则获取锁成功,如果失败则撤销偏向锁。
  • 如果不为空则检查 线程 id为是否为本线程。如果是则获取锁成功,如果失败则撤销偏向锁。

持有偏向锁的线程以后每次进入这个锁相关的同步块时,只需比对一下 mark word 的线程 id 是否为本线程,如果是则获取锁成功。

如果发生线程竞争发生 2、3 步失败的情况则需要撤销偏向锁。

偏向锁的撤销
  1. 偏向锁的撤销动作必须等待全局安全点
  2. 暂停拥有偏向锁的线程,判断锁对象是否处于被锁定状态
  3. 撤销偏向锁恢复到无锁(标志位为 01)或轻量级锁(标志位为 00)的状态
优点

只有一个线程执行同步块时进一步提高性能,适用于一个线程反复获得同一锁的情况。偏向锁可以提高带有同步但无竞争的程序性能。

缺点

如果存在竞争会带来额外的锁撤销操作。

轻量级锁
加锁

多个线程竞争偏向锁导致偏向锁升级为轻量级锁

  1. JVM 在当前线程的栈帧中创建 Lock Reocrd,并将对象头中的 Mark Word 复制到 Lock Reocrd 中。(Displaced Mark Word)
  2. 线程尝试使用 CAS 将对象头中的 Mark Word 替换为指向 Lock Reocrd 的指针。如果成功则获得锁,如果失败则先检查对象的 Mark Word 是否指向当前线程的栈帧如果是则说明已经获取锁,否则说明其它线程竞争锁则膨胀为重量级锁。
解锁
  1. 使用 CAS 操作将 Mark Word 还原
  2. 如果第 1 步执行成功则释放完成
  3. 如果第 1 步执行失败则膨胀为重量级锁。
优点

其性能提升的依据是对于绝大部分的锁在整个生命周期内都是不会存在竞争。在多线程交替执行同步块的情况下,可以避免重量级锁引起的性能消耗。

缺点

在有多线程竞争的情况下轻量级锁增加了额外开销。

自旋锁

自旋是一种获取锁的机制并不是一个锁状态。在膨胀为重量级锁的过程中或重入时会多次尝试自旋获取锁以避免线程唤醒的开销,但是它会占用 CPU 的时间因此如果同步代码块执行时间很短自旋等待的效果就很好,反之则浪费了 CPU 资源。默认情况下自旋次数是 10 次用户可以使用参数 -XX : PreBlockSpin 来更改。那么如何优化来避免此情况发生呢?我们来看适应性自旋。

适应性自旋锁

JDK 6 引入了自适应自旋锁,意味着自旋的次数不在固定,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。如果对于某个锁很少自旋成功那么以后有可能省略掉自旋过程以避免资源浪费。有了自适应自旋随着程序运行和性能监控信息的不断完善,虚拟机对程序锁的状况预测就会越来越准确,虛拟机就会变得越来越“聪明”了。

优点

竞争的线程不会阻塞挂起,提高了程序响应速度。避免重量级锁引起的性能消耗。

缺点

如果线程始终无法获取锁,自旋消耗 CPU 最终会膨胀为重量级锁。

重量级锁

在重量级锁中没有竞争到锁的对象会 park 被挂起,退出同步块时 unpark 唤醒后续线程。唤醒操作涉及到操作系统调度会有额外的开销。

ObjectMonitor 中包含一个同步队列(由 _cxq_EntryList 组成)一个等待队列( _WaitSet )。

  • 被notify或 notifyAll 唤醒时根据 policy 策略选择加入的队列(policy 默认为 0)
  • 退出同步块时根据 QMode 策略来唤醒下一个线程(QMode 默认为 0)

这里稍微提及一下管程这个概念。synchronized 关键字及 waitnotifynotifyAll 这三个方法都是管程的组成部分。可以说管程就是一把解决并发问题的万能钥匙。有两大核心问题管程都是能够解决的:

  • 互斥:即同一时刻只允许一个线程访问共享资源;
  • 同步:即线程之间如何通信、协作。

synchronizedmonitor锁机制和 JDK 并发包中的 AQS 是很相似的,只不过 AQS 中是一个同步队列多个等待队列。熟悉 AQS 的同学可以拿来做个对比。

3.3 锁升级过程

锁的升级是自动的,以减少锁的开销。例如,从偏向锁到轻量级锁的升级发生在第一个获取偏向锁的线程之外的线程尝试获取这个锁时。

3.4 对象头和锁标记位

Java对象头包含了对象的运行时数据,例如哈希码、GC标记位、锁状态等。这些信息对于锁的管理至关重要。
在这里插入图片描述

附录:队列协作流程图

在这里插入图片描述

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

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

相关文章

创新书荐|用《创新者的窘境》指导企业应对AI颠覆技术避免被颠覆

如何利用《创新者的窘境》应对AI的颠覆性技术时,了解并实施正确的战略对于确保企业在动荡的市场环境中保持增长和竞争力至关重要。我们分析了市场领导者和初创公司如何利用AI开辟新的增长路径,以及企业如何在技术革命中维持竞争优势。想要深入了解并实践…

CogVLM CogAgent模型部署

CogVLM & CogAgent 下载地址 CogVLM & CogAgent 的 Github 官方仓库:https://github.com/THUDM/CogVLM CogVLM & CogAge…

了解ASK模块STX883Pro和超外接收模块SRX883Pro的独特之处 STX883Pro模块具有以下特点:

高发射功率:STX883Pro具有较高的发射功率,可实现长距离的信号传输,适用于需要覆盖广泛区域的应用场景。 高频率稳定性:具备稳定的频率输出,确保信号传输的可靠性和一致性,避免频率漂移导致的通信故障。 大…

异常检测 | SVDD支持向量数据描述异常数据检测(Matlab)

异常检测 | SVDD支持向量数据描述异常数据检测(Matlab) 目录 异常检测 | SVDD支持向量数据描述异常数据检测(Matlab)效果一览基本介绍程序设计参考资料 效果一览 基本介绍 用于一类或二元分类的 SVDD 模型 多种核函数(…

基于模糊控制的电动汽车锂电池SOC主动均衡电路MATLAB仿真模型

微❤关注“电气仔推送”获得资料(专享优惠) 模型简介 模型在 Matlab/Simulink仿真平台中搭建16节电芯锂电池电路模型,主要针对电动车锂电池组SOC差异性,采用模糊控制算法动态调节均衡电流,以减少均衡时间和能量损耗。…

换脸插件升级导致SDWebUI无法启动cannot import name ‘Undefined‘ from ‘pydantic.fields‘

今天在一台新的机器环境装了SDWEBUI,都使用最新的版本,升级了下换脸的插件,于是乎启动崩溃了。错误如下 Launching Web UI with arguments: --listen --skip-torch-cuda-test --disable-nan-check --skip-version-check --skip-python-versi…

SQL嵌套查询和集合查询

嵌套查询 先导概念 查询块:一个select语句为一个查询块 嵌套查询:将一个查询块嵌套在一个另一个查询块中where子句中的查询叫做嵌套查询。 嵌套查询的种类: 不相关子查询:子查询里的条件不依赖于父查询,从里到外依…

android布局

LinerLayout 权重分配的是剩余空间 RelativeLayout

Python脚本实现PC端大麦网自动购票(Selenium自动化测试工具)

文章目录 Selenium 简介Selenium webdriver 文档chromedriver(谷歌浏览器驱动)chromedriver 下载配置环境变量 大麦网购票脚本网页 dom 元素 启用远程调试(操作已打开的窗口) Selenium 简介 Selenium 是一个用于自动化测试的工具…

目标检测与追踪AI算法模型及边缘计算智能分析网关V4的算法应用

目标检测与追踪是计算机视觉领域中的一个重要任务,主要用于识别图像或视频中的目标,并跟踪它们的运动轨迹。针对这一任务,有许多先进的AI算法模型,例如: YOLO(You Only Look Once):…

linux 设备树-of_address_to_resource

实例分析-reg 属性解析(基于ranges属性) /{#address-cells <0x01>;#size-cells <0x01>;soc {compatible "simple-bus";#address-cells <0x01>;#size-cells <0x01>;ranges <0x7e000000 0x3f000000 0x1000000 0x40000000 0x40000000…

怎么把图片转换为二维码?3个步骤轻松制作图片二维码

图片的二维码是怎么做成的呢&#xff1f;现在很多场景下的二维码&#xff0c;用手机扫码可以展现出对应的图片信息。通过这种方式来传递图片对于用户体验与很好的效果&#xff0c;而且也方便制作者通过这种方式来快速完成图片信息的传递&#xff0c;与传统方式相比成本更低&…

客服专用的宝藏快捷回复软件

提起客服&#xff0c;很多人会觉得现在智能机器人的自动回复功能就可以将其替代。我始终不是这么认为的。人工客服始终能为一家店铺乃至一个企业起着非常关键重要的作用。今天就来给大家推荐一个客服专用的宝藏软件——客服宝聊天助手。感兴趣的话&#xff0c;可以发给你的客服…

面向对象开发技术(第三周)

回顾 上一堂课主要学习了面向对象编程与非面向对象编程&#xff08;面向功能、过程编程&#xff09;&#xff0c;本节课就重点来看看面向对象编程中的一个具体思想——抽象 面向对象编程的特性&#xff1a;1、封装性 2、继承性 3、多态性 封装&#xff1a;意味着提供服务接口…

异常风云:解码 Java 异常机制

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一个人虽可以走的更快&#xff0c;但一群人可以走的更远。 我是一名后…

【论文阅读】《Octopus v2: On-device language model for super agent》,端侧大模型的应用案例

今年LLM的发展趋势之一&#xff0c;就是端侧LLM快速发展&#xff0c;超级APP入口之争异常激烈。不过&#xff0c;端侧LLM如何应用&#xff0c;不知道细节就很难理解。正好&#xff0c;《Octopus v2: On-device language model for super agent》这篇文章可以解惑。 对比部署在…

JTAG访问xilinx FPGA的IDCODE

之前调试过xilinx的XVC&#xff08;Xilinx virtual cable&#xff09;&#xff0c;突然看到有人搞wifi-JTAG&#xff08;感兴趣可以参考https://github.com/kholia/xvc-esp8266&#xff09;&#xff0c;也挺有趣的。就突然想了解一下JTAG是如何运作的&#xff0c;例如器件识别&…

普通话水平测试用朗读作品60篇-(练习版)

普通话考试题型有读单音节字词、读多音节字词、朗读作品和命题说话。 具体分值如下&#xff1a; 1、读单音节字词100个&#xff0c;占10分&#xff1b;目的考查应试人普通话声母、韵母和声调的发音。 2、读双音节词语50个&#xff0c;占20分&#xff1b;目的是除了考查应试人声…

骨传导耳机怎么选?精心挑选热销排行前五的骨传导耳机推荐!

近几年&#xff0c;骨传导耳机作为新型蓝牙耳机款式&#xff0c;已经得到大家有效认可&#xff0c;可以说已经适用于日常中的各种场景中&#xff0c;比如运动场景&#xff0c;凭借舒适的佩戴体验和保护运动安全的特点深受到运动爱好者的欢迎&#xff0c;作为一个经验丰富的数码…

Linux网络—DNS域名解析服务

目录 一、BIND域名服务基础 1、DNS系统的作用及类型 DNS系统的作用 DNS系统类型 DNS域名解析工作原理&#xff1a; DNS域名解析查询方式&#xff1a; 2、BIND服务 二、使用BIND构建域名服务器 1、构建主、从域名服务器 1&#xff09;主服务器配置&#xff1a; 2&…
最新文章