JAVAEE多线程synchronized 优化过程

news/2024/4/30 12:39:29/文章来源:https://blog.csdn.net/m0_58437435/article/details/126960183

文章目录

  • synchronized 优化过程
    • 一、锁升级/锁膨胀
      • 1. 偏向锁
      • 2. 轻量级锁
      • 3. 重量级锁
    • 二、锁消除
    • 三、锁粗化
  • 总结


synchronized 优化过程

对于synchronized

1.既是乐观锁,也是悲观锁
2.既是轻量级锁,也是重量级锁
3.乐观锁的部分是基于自旋锁实现的,悲观锁的部分是基于挂起等待锁实现的
4.不是读写锁,普通互斥锁
5.是非公平锁
6.是可重入锁

synchronized是自适应的!!!
synchronized初始使用的时候,是 乐观锁/轻量级锁/自旋锁
如果锁竞争激烈,synchronized会自动升级成 悲观锁/重量级锁/挂起等待锁

JVM在实现synchronized的时候给我们提供自动优化的策略~
一个synchronized 自动适应多种不同的场景!!
在这里插入图片描述

一、锁升级/锁膨胀

synchronized的效果是"加锁"

当两个线程针对同一个对象加锁的时候,就会出现锁竞争~
后来尝试加锁的线程就得阻塞等待,直到前一个线程释放锁~

synchronized加锁的具体过程:

  1. 偏向锁
  2. 轻量级锁
  3. 重量级锁

synchronized 更多的考虑到程序员的使用负担,内部就实现了"自适应"这样的操作.

如果当前场景中,锁竞争不激烈,则是以轻量级锁状态来进行工作(自旋,第一时间拿到锁)

如果当前场景中,锁竞争激烈,则是以重量级锁状态来进行工作(挂起等待,拿到锁没那么及时,但是节省了开销)

无竞争,偏向锁
有竞争,轻量级锁
竞争激烈,重量级锁

上述的变化就叫做锁升级/锁膨胀

JVM实现synchronized的时候,为了方便程序员使用,引入的一些优化机制~

在这里插入图片描述

1. 偏向锁

偏向锁的本质类似于懒汉模式~
必要的时候再加锁,能不加就不加~

比如我给某个线程加了个synchronized,但是这个代码实际执行过程中,不一定会触发锁竞争!
类似count++ :

如果两个线程本身调度的时候恰好错开了,此时t1t2的锁竞争并没有真的发生 如果不是真的发生了锁竞争,就没有必要真的加锁
在这里插入图片描述
但是如果这种情况:
在这里插入图片描述
如果没有t2的竞争,t1的锁就不生效,有了竞争才正式生效。
这种不是真实生效的状态,就叫偏向锁

偏向锁不是真加锁,而是只是设置了一个状态~
如果没有其他线程参与竞争锁, 那么就不会真正执行加锁操作, 从而降低程序开销.
一旦真的涉及到其他的线程竞争, 再取消偏向锁状态, 进入轻量级锁状态.

在这里插入图片描述

2. 轻量级锁

随着其他线程进入竞争, 偏向锁状态被消除, 进入轻量级锁状态(自适应的自旋锁).
此处的轻量级锁就是通过 CAS 来实现

  • 通过 CAS 检查并更新一块内存 (比如 null => 该线程引用)
  • 如果更新成功, 则认为加锁成功
  • 如果更新失败, 则认为锁被占用, 继续自旋式的等待(并不放弃 CPU).

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

3. 重量级锁

如果竞争进一步激烈, 自旋不能快速获取到锁状态, 就会膨胀为重量级锁
此处的重量级锁就是指用到内核提供的 mutex .

  • 执行加锁操作, 先进入内核态.
  • 在内核态判定当前锁是否已经被占用
  • 如果该锁没有占用, 则加锁成功, 并切换回用户态.
  • 如果该锁被占用, 则加锁失败. 此时线程进入锁的等待队列, 挂起. 等待被操作系统唤醒.
  • 经历了一系列的沧海桑田, 这个锁被其他线程释放了, 操作系统也想起了这个挂起的线程, 于是唤醒这个线程, 尝试重新获取锁.

在这里插入图片描述

二、锁消除

JVM自动判定,发现这个地方的代码,不必加锁,如果写了synchronized,就会自动的把锁给去掉!!

🎠举个例子:

比如我只有一个线程/或者有多个线程,多个线程不涉及修改同一个变量,如果代码中也写了synchronized,此时synchronized加锁操作,就会直接被JVM给干掉~

synchronized加锁应该是 先偏向锁 !

锁消除也是一种编译器优化的行为~
编译器的判定,不一定非常准!

因此如果代码的锁100%能消除, 就消除了.
如果这个代码的锁,判定不准能不能消除(判定80%的可能是可以消除,20%的可能不能消除),就还是不消除了

因此锁消除只是在编译器/JVM有十足的把握的时候才进行的!!

在这里插入图片描述

三、锁粗化

锁的粒度:
synchronized对应的代码块包含多少代码,包含的代码少,就叫粒度细,包含的代码多,就叫粒度粗~

锁粗化,就是把细粒度的加锁转化为粗粒度的加锁

比如下图:

在这里插入图片描述
一开始加锁解锁很多次,锁粗化就直接把中间的全部清除,只留开头和结尾的加锁和解锁
因为每次解锁再加锁就会带来额外的锁竞争,带来更大的开销

粗化的前提是保证你的逻辑不变~
细化的时候代码是正确的,粗化之后代码还是正确的~

锁的粒度也不是越粗越好~
有的时候锁太粗不利于多线程并发,有悖于之前写多线程的初衷了…

总结

在这里插入图片描述

你可以叫我哒哒呀
本篇到此结束
“莫愁千里路,自有到来风。”
我们顶峰相见!

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

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

相关文章

springboot+jsp云课堂在线教育系统javaweb

“云课堂”在线教育系统是由高校学生依据兴趣爱好自愿组成,按照章程自主开展在线教育课程。“云课堂”在线教育系统是实施素质教育的重要途径和有效方式,在加强校园文化建设、提高学生综合素质、引导学生适应社会、促进学生成才就业等方面发挥着重要作用…

【23种设计模式】组合模式(Composite Pattern) .Net Core实现

文章目录需求变更我们应该怎么做?组合和单个对象是指什么呢?使用组合模式来设计菜单组合迭代器来源组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象&…

【服务器数据恢复】AIX环境下误删除逻辑卷的数据恢复方案

一、AIX存储层面相关的知识&AIX环境下LV误删除后的恢复方案。 对于AIX而言,PV相当于物理磁盘,一个VG由若干个PV组成,这让我们可以将容量不同的存储空间组合起来进行统一分配。AIX把同一个VG的所有PV按相同大小的存储颗粒(PP&…

自制操作系统系列(二):软盘读取

代码仓库地址:https://github.com/freedom-xiao007/operating-system 简介 在上一篇中,我们使用汇编编写了一个直接显示hello的程序,接下来我们继续探索如果使用汇编读取软盘数据 软盘数据读取准备 在上一篇中,我们使用nasm将…

让运维化繁为简,云原生可观测平台 Alibaba Cloud Lens 正式发布

9 月 28 日,阿里云正式推出云产品可观测平台 Alibaba Cloud Lens(Lens 透镜,意为洞察细微变化),从成本、性能、安全、数据保护、稳定性、访问分析六个维度,为用户提供对存储类、网络类、数据库类等云产品的…

还在埋头敲代码?不妨学学设计模式,必能让你工作事半功倍

设计模式在开发中占很重要的地位;在大型项目中使用好设计模式往往会取得事半功倍的效果;下面就介绍下几种在开发中常用到的设计模式 装饰者模式(Decorator Pattern) 装饰者模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的…

中断系统:外部中断

中断系统:外部中断 实现功能 按下独立按键Key3,LED流水灯向右;按下Key4,LED流水灯向左。 单片机型号:STC89C52 硬件原理 中断系统就是当系统在进行一项工作时,需要终止这项工作,转而去执行另一…

Springboot复习

本笔记来自b站尚硅谷 文章目录SpringbootHelloWorld原理Value获取值和ConfigurationProperties获取值比较PropertySource 和 ImportResourceprofile自动配置原理整合日志指定配置全面接管SpringMVC启动流程自定义starterdev-toolsyml提示指标监控Springboot HelloWorld原理 配置…

Python函数练习题:通讯录管理程序实战案例

嗨害大家好鸭!我是小熊猫❤ 好久没有整实战案例类文章辽 今天就来整一整~ 功能简介 实现一个通讯录管理程序,使用函数来实现程序,采用模块化的程序设计方法: 划分通讯录程序的功能模块,使用函数实现相应的功能首先…

数据湖-hudi概述

前言 数据湖是目前比较热的一个概念,许多企业都在构建或者计划构建自己的数据湖。 数据湖是一个集中式存储库,允许您以任意规模存储所有结构化和非结构化数据。您可以按原样存储数据(无需先对数据进行结构化处理),并运…

nginx80转443

多了一个server,做了一个301的跳转 server { listen 80; server_name www.web1.com web1.com; (这里是可写别名的,第二个是别名) return 301 https://www.web1.com$request_uri; (当别人访问80,让它转到…

智能网联-浅谈基于PKI的车联网应用服务安全

智能网联-浅谈基于PKI的车联网应用服务安全 面对车联网快速发展趋势,信息安全是一项必要的防护措施。车端应用数字证书可认证合法身份,保障数据加密通信,防止信息的泄露与攻击。基于PKI的车联网应用服务安全认证体系框架,从国家层…

Java多线程的创建与Thread类的方法及使用

Java多线程的创建与Thread类的方法及使用🍎一.Thread类的属性与方法🍇1.1什么是线程🍇1.2Thread类的基础常见的构造方法🍇1.3Thread的常见属性🍇1.4Thread类常用的基础方法🍎二.Java线程的创建&#x1f347…

6步搭建一个飞机大战游戏

摘要:本文以华为云软件开发平台DevCloud为例,展示飞机大战游戏开发的DevOps实践流程。DevOps实践 DevOps实践是一种开发、测试运维一体化的模式,其实践的外在表现一般包括了如代码仓库、构建、测试、发布、配置、监控等工具形成的一个完整的…

引擎之旅 Chapter.3 文件系统

文章目录引言在此之前...Unicode和ASCIIC风格字符串的操作函数集合字符串操作字符串类型转换Part1:操作文件名和文件路径Part2:单个文件的读写文件打开的模式TFile的定义Part3:异步文件I/O异步I/O线程文件类中的异步方法引言 为什么会将文件…

数据中台开源解决方案(一)

数据中台商业的解决方案有很多,开源框架种类繁多,每一个模块都有很多开源的套件。以查询引擎为例,可以使用的开源工具有MySQL、Redis、Impala、MongoDB、PgSQL等。可以根据实际业务需要,选择合适的开源套件。 可供选择的解决方案太多,重点推荐开源解决方案,框架图如下图所…

【RCJ-2 AC220V 0.015A静态冲击继电器】

系列型号 RCJ-2/48VDC冲击继电器 RCJ-2/110VDC冲击继电器 RCJ-2/220VDC冲击继电器 RCJ-2/100VAC冲击继电器 RCJ-2/127VAC冲击继电器 RCJ-2/220VAC冲击继电器 RCJ-3/220VAC冲击继电器 RCJ-3/127VAC冲击继电器 RCJ-3/100VAC冲击继电器 RCJ-3/220VDC冲击继电器 RCJ-3/110VDC冲击继…

【论文笔记】CIKM‘22 & Amazon | (Navip) 推荐系统中图神经网络的去偏邻域聚合

目录1. Introduction2. Related Work2.1 基于GNN的推荐2.2 逆倾向评分IPS3. 模型3.1 Navip4. 实验结果本文是亚马逊在CIKM 2022的一篇工作 论文地址:https://arxiv.org/pdf/2208.08847.pdf 问题 图形神经网络(GNN)对于曝光偏差的脆弱性导致模型偏差,产生…

09-Pytorch中的序列化容器

目录 1.梯度消失和梯度爆炸 1.1 梯度消失 1.2 梯度爆炸 1.3 解决梯度消失或梯度爆炸的经验 2.nn.Sequential 3.nn.BatchNorm1d 4.nn.Dropout 1.梯度消失和梯度爆炸 在使用pytorch中的序列化容器之前,我们先来了解一下常见的梯度消失和梯度爆炸的问题。 1.1 …

②、HTML 元素学习

HTML 元素 HTML 文档由 HTML 元素定义。 HTML 元素 *开始标签常被称为起始标签(opening tag),结束标签常称为闭合标签(closing tag)。 HTML 元素语法 HTML 元素以开始标签起始HTML 元素以结束标签终止元素的内容是开始…