一文带你了解Java中synchronized原理

🌈🌈🌈今天给大家分享的是Java中 synchronized 的基本原理 

清风的CSDN博客

🛩️🛩️🛩️希望我的文章能对你有所帮助,有不足的地方还请各位看官多多指教,大家一起学习交流!

✈️✈️✈️动动你们发财的小手,点点关注点点赞!在此谢过啦!哈哈哈!😛😛😛

目录

一、synchronized 基本特点 

二、加锁工作过程 

2.1 偏向锁 

2.2 轻量级锁 

2.3 重量级锁 

 三、其他的优化操作

3.1 锁消除 

3.2 锁粗化 


 

一、synchronized 基本特点 

结合上篇文章给大家分享的锁策略 , 我们就可以总结出 , Synchronized 具有以下特性 ( 只考虑 JDK 1.8)。
  • 开始时是乐观锁, 如果锁冲突频繁, 就转换为悲观锁
  • 开始是轻量级锁实现, 如果锁被持有的时间较长, 就转换成重量级锁
  • 实现轻量级锁的时候大概率用到的自旋锁策略
  • 是一种不公平锁
  • 是一种可重入锁
  • 不是读写锁

二、加锁工作过程 

JVM synchronized 锁分为 无锁、偏向锁、轻量级锁、重量级锁 状态。会根据情况,进行依次升级。 

2.1 偏向锁 

第一个尝试加锁的线程 , 优先进入偏向锁状态。
  • 偏向锁不是真的 "加锁", 只是给对象头中做一个 "偏向锁的标记", 记录这个锁属于哪个线程
  • 如果后续没有其他线程来竞争该锁, 那么就不用进行其他同步操作了(避免了加锁解锁的开销)
  • 如果后续有其他线程来竞争该锁(刚才已经在锁对象中记录了当前锁属于哪个线程了, 很容易识别当前申请锁的线程是不是之前记录的线程), 那就取消原来的偏向锁状态, 进入一般的轻量级锁状态。
  • 偏向锁本质上相当于 "延迟加锁", 能不加锁就不加锁, 尽量来避免不必要的加锁开销。
    但是该做的标记还是得做的, 否则无法区分何时需要真正加锁。

举个例子理解偏向锁:

假设男主是一个锁, 女主是一个线程。如果只有这一个线程来使用这个锁, 那么男主女主即使不领证结婚(避免了高成本操作), 也可以一直幸福的生活下去。
但是女配出现了, 也尝试竞争男主, 此时不管领证结婚这个操作成本多高, 女主也势必要把这个动作完成了, 让女配死心。

2.2 轻量级锁 

随着其他线程进入竞争 , 偏向锁状态被消除 , 进入轻量级锁状态 ( 自适应的自旋锁 )。此处的轻量级锁就是通过 CAS(后面我会给大家详细介绍)  来实现。
  • 通过 CAS 检查并更新一块内存 (比如 null => 该线程引用)
  • 如果更新成功, 则认为加锁成功
  • 如果更新失败, 则认为锁被占用, 继续自旋式的等待(并不放弃 CPU)

自旋操作是一直让 CPU 空转, 比较浪费 CPU 资源。因此此处的自旋不会一直持续进行, 而是达到一定的时间/重试次数, 就不再自旋了。也就是所谓的 "自适应"。

2.3 重量级锁 

如果竞争进一步激烈 , 自旋不能快速获取到锁状态 , 就会膨胀为重量级锁,此处的重量级锁就是指用到内核提供的 mutex 。
  • 执行加锁操作, 先进入内核态
  • 在内核态判定当前锁是否已经被占用
  • 如果该锁没有占用, 则加锁成功, 并切换回用户态
  • 如果该锁被占用, 则加锁失败, 此时线程进入锁的等待队列, 挂起等待被操作系统唤醒
  • 经历了一系列的沧海桑田, 这个锁被其他线程释放了, 操作系统也想起了这个挂起的线程, 于是唤醒这个线程, 尝试重新获取锁

 三、其他的优化操作

3.1 锁消除 

编译器+JVM 判断锁是否可消除,如果可以, 就直接消除。什么是 "锁消除"

 有些应用程序的代码中, 用到了 synchronized, 但其实没有在多线程环境下,(例如 StringBuffer)

StringBuffer sb = new StringBuffer();
sb.append("a");
sb.append("b");
sb.append("c");
sb.append("d");
此时每个 append 的调用都会涉及加锁和解锁,但如果只是在单线程中执行这个代码, 那么这些加
锁解锁操作是没有必要的, 白白浪费了一些资源开销。

3.2 锁粗化 

一段逻辑中如果出现多次加锁解锁 , 编译器 + JVM 会自动进行锁的粗化。
锁的粒度: 粗和细
实际开发过程中, 使用细粒度锁, 是期望释放锁的时候其他线程能使用锁。但是实际上可能并没有其他线程来抢占这个锁,这种情况 JVM 就会自动把锁粗化, 避免频繁申请释放锁。

举个例子理解锁粗化:

滑稽老哥当了领导, 给下属交代工作任务:
方式一:
  • 打电话, 交代任务1, 挂电话
  • 打电话, 交代任务2, 挂电话
  • 打电话, 交代任务3, 挂电话

方式二:

  • 打电话, 交代任务1, 任务2, 任务3, 挂电话
显然, 方式二是更高效的方案。

 


🌈🌈🌈好啦,今天的分享就到这里!

🛩️🛩️🛩️希望各位看官读完文章后,能够有所提升。

🎉🎉🎉创作不易,还希望各位大佬支持一下!

✈️✈️✈️点赞,你的认可是我创作的动力!

⭐⭐⭐收藏,你的青睐是我努力的方向!

✏️✏️✏️评论:你的意见是我进步的财富!

 

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

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

相关文章

2023 年 O 基础学习 SwiftUI

关于 SwiftUI SwiftUI 于2019年6月3日在苹果的全球开发者大会(WWDC)上首次亮相。在这次活动中,苹果正式宣布了 SwiftUI,并将其列为 iOS 13 和 macOS Catalina 的一部分。 SwiftUI 是一种用于构建用户界面的 UI 框架。SwiftUI 的设…

Servlet基础知识

Servlet是Java提供的一门动态的web资源开发技术 Servlet是JavaEE规范之一&#xff0c;其实就是一个接口&#xff0c;将来我们需要定义Servlet类实现Servlet接口&#xff0c;并由web服务器运行Servelt Servlet快速入门 创建web项目&#xff0c;导入Servlet依赖坐标 <depe…

百度Apollo新版本Beta技术沙龙参会体验

在自动驾驶领域&#xff0c;百度的Apollo一直是业界开源的标杆。其持续升级和创新的开源项目为整个自动驾驶行业树立了典范&#xff0c;不仅推动了技术的发展&#xff0c;也为广大的社区开发者们提供了学习和参考的范本。最近百度发布了Apollo新的Beta版本&#xff0c; 新版本B…

【PID学习笔记 6 】控制系统的性能指标之二

写在前面 上文介绍了控制系统的稳态与动态、过渡过程、阶跃响应以及阶跃信号作用下过渡过程的四种形式。本文紧接上文&#xff0c;首先总结过渡过程的分类&#xff0c;然后介绍控制系统的性能评价&#xff0c;最后重点介绍控制系统性能指标中的单项指标。 一、过渡过程的分类…

四.多表查询

多表查询 1.一个案例引发的多表连接1.1案例说明1.2 笛卡尔积&#xff08;或交叉连接&#xff09;的理解1.3案例分析与问题解决 2.多表查询分类讲解分类1&#xff1a;等值连接vs非等值连接分类2&#xff1a;自连接vs非自连接分类3&#xff1a;内连接vs外连接 3.SQL99语法实现多表…

读书笔记-《数据结构与算法》-摘要2[冒泡排序]

冒泡排序 核心&#xff1a;冒泡&#xff0c;持续比较相邻元素&#xff0c;大的挪到后面&#xff0c;因此大的会逐步往后挪&#xff0c;故称之为冒泡。 public class BubbleSort {public static void main(String[] args) {int unsortedArray[] new int[]{6, 5, 3, 1, 8, 7, 2…

旋转设备状态监测与预测性维护:提高设备可靠性的关键

在工业领域的各个行业中&#xff0c;旋转设备都扮演着重要的角色。为了确保设备的可靠运行和预防潜在的故障&#xff0c;旋转设备状态监测及预测性维护变得至关重要。本文将介绍一些常见的旋转设备状态监测方法&#xff0c;并探讨如何利用这些方法来实施预测性维护&#xff0c;…

Java的第二十一章:网络通信

网络程序设计基础 网络程序设计编写的是与其他计算机进行通信的程序。Java 已经将网络程序所需要的元素封装成不同的类&#xff0c;用户只要创建这些类的对象&#xff0c;使用相应的方法&#xff0c;即使不具备有关的网络支持&#xff0c;也可以编写出高质量的网络通信程序。 …

周周爱学习之快速排序

快速排序&#xff0c;顾名思义&#xff0c;快速排序是一种速度非常快的一种排序算法 平均时间复杂度为O(),最坏时间复杂度为O()数据量较大时&#xff0c;优势非常明显属于不稳定排序 1.算法描述 每一轮排序选择一个基准点&#xff08;pivot&#xff09;进行分区 让小于基准点…

supervisord + nginx + Daphne + django4.0 最新asgi服务器部署实验

由于需要用到channel&#xff0c;最近在研究通过asgi部署django。 先吐槽一下官方文档&#xff0c;这个地方讲的非常简单。然后中文互联网环境能找到的都是3.0试用的说明&#xff0c;这玩意是不是真的没人用啊&#xff1f;还是说Django已经脱离时代了。。。 简单研究了一下&am…

洗地机好用吗?口碑好的洗地机有哪些?

自从洗地机开始引入市场以来&#xff0c;它一直受到人们的关注。它在解放家庭清洁劳动力和提供快速方便的清洁方面表现出色&#xff0c;超越了多年来传统的拖把清洁方式。越来越多的人选择使用洗地机来完成家庭清洁任务。如果你也对洗地机产生了浓厚的兴趣&#xff0c;并想购买…

【MATLAB源码-第93期】基于matlab的白鲸优化算法(BWO)和鲸鱼优化算法(WOA)机器人栅格路径规划对比。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 白鲸优化算法&#xff08;BWO&#xff09; 白鲸优化算法是受到白鲸捕食和迁徙行为启发的一种算法。其主要特点和步骤包括&#xff1a; 1. 搜索食物&#xff08;全局搜索&#xff09;&#xff1a;算法模仿白鲸寻找食物的行为。…

【模型报错记录】‘PromptForGeneration‘ object has no attribute ‘can_generate‘

通过这个连接中的方法解决&#xff1a; “PromptForGeneration”对象没有属性“can_generate” 期刊 #277 thunlp/OpenPrompt GitHub的 问题描述&#xff1a;在使用model.generate() 的时候报错&#xff1a;PromptForGeneration object has no attribute can_generate 解决方法…

Java中子类都继承父类的什么?

1.构造方法 构造方法不可以被继承的&#xff0c;为什么呢&#xff1f;应为名称的定义&#xff0c;构造方法是一类名称与类名一致&#xff0c;无返回值和类型修饰的一种。所以如果子类继承父类的构造方法的话&#xff0c;那么就违背了构造方法的规定。 2.成员属性 成员属性是…

C# Demo--汉字转拼音

1.Nuget安装NPOI及Pinyin4net 2.Demo 代码部分 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NPOI.SS.UserModel; using NPOI.HSSF.UserModel; using NPOI.XSSF.UserModel; using System.IO;…

【Linux】基础IO--重定向理解Linux下一切皆文件缓冲区

文章目录 一、重定向1.什么是重定向2.dup2 系统调用3.理解输入重定向、输出重定向和追加重定向4.简易shell完整实现 二、理解linux下一切皆文件三、缓冲区1.为什么要有缓冲区2.缓冲区的刷新策略3.缓冲区的位置4.实现一个简易的C语言缓冲区5.内核缓冲区 一、重定向 1.什么是重定…

【5】PyQt按钮

QPushButton 常见的按钮实现类包括:QPushButton、QRadioButton和QCheckBox QPushButton是最普通的按钮控件&#xff0c;可以响应一些用户的事件 from PyQt5.QtWidgets import QApplication, QWidget, QPushButton import sysdef func():print("按下按钮啦&#xff0c;火…

YOLOv8优化策略:简单高效的模块-现代反向残差移动模块 (iRMB) | | ICCV2023 EMO

🚀🚀🚀本文改进:设计了一种面向移动端应用的简单而高效的现代反向残差移动模块 (Inverted Residual Mobile Block, iRMB),它吸收了类似 CNN 的效率来模拟短距离依赖和类似 Transformer 的动态建模能力来学习长距离交互,引入YOLOV8 🚀🚀🚀YOLOv8改进专栏:http:…

Python神器解析时间序列数据:数据分析者必读

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 时间序列数据是在许多领域中都至关重要的数据类型&#xff0c;它涵盖了一系列按时间顺序排列的数据点。Python作为一种强大的数据分析工具&#xff0c;提供了许多库和工具&#xff0c;能够有效地处理、分析和可视…

2D与3D图形的基本变换

1. 2d transformations 1.1缩放(Scaling) 其实这个转换非常简单&#xff0c;如图所示就是把x与y进行s倍的缩放&#xff0c;而我们图中的这个矩阵正好满足这一算法。 1.2镜像(Reflection) 这个镜像变换可以和上面的做类比&#xff0c;简单看一下就行。 1.3错切(Shearing) 当然…