锁升级过程与优化操作

前文我们学习了CAS自旋锁知道CAS对应的就是一条指令操作,属于一种轻量级锁,那么有轻必有重,从无锁到轻量级锁到重量级锁是一个升级过程,此文我们对锁升级的过程以及一些优化锁的操作一探究竟。

1. 锁升级

从前文 《程序员不可能不知道的锁策略》 一文中,结合锁策略,我们就可以总结出,synchronized 具有以下特性 (只考虑JDK1.8) :

  1. 开始时是乐观锁,如果锁冲突频繁,就转换为悲观锁.
  2. 开始是轻量级锁实现,如果锁被持有的时间较长,就转换成重量级锁.
  3. 实现轻量级锁的时候大概率用到的自旋锁策略
  4. 是⼀种不公平锁
  5. 是⼀种可重入锁
  6. 不是读写锁

加锁工作过程:

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

在这里插入图片描述

  1. 无锁
    不存在锁

  2. 偏向锁
    偏向锁是Java中最轻量级的锁升级策略。 当一个线程获取到锁时,该锁会进入偏向模式,并将获取到锁的线程ID记录下来 (做标记)。接下来,当这个线程再次请求同一个锁时,无需竞争,可以直接获取,(避免了加锁解锁的开销)。偏向锁本质上相当于"延迟加锁".能不加锁就不加锁,尽量来避免不必要的加锁开销.但是该做的标记还是得做的,否则⽆法区分何时需要真正加锁.这种策略适用于大部分情况下都是由同一个线程持有锁的场景。

  3. 轻量级锁
    当多个线程同时请求同一个锁时,偏向锁就无法满足需求,锁升级到轻量级锁。 轻量级锁使用CAS(Compare and Swap)操作来避免线程的阻塞和唤醒,从而提高并发性能。当线程获取轻量级锁失败时,锁会升级到下一个阶段。

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

  1. 自旋锁
    自旋锁是轻量级锁升级的一种策略。 当线程在获取轻量级锁失败后,它不会立即被挂起,而是会自旋一段时间,不断尝试获取锁。自旋锁的目的是为了避免线程的上下文切换,提高性能。但如果自旋时间过长或者自旋次数达到一定阈值,仍然没有成功获取锁,那么锁将会升级到下一个阶段。

  2. 重量级锁
    重量级锁是Java中最重量级的锁升级策略。 当自旋锁尝试获取锁的次数达到阈值时,锁会进入重量级模式。重量级锁采用操作系统的互斥锁实现,真正的调用CPU的指令LOCK

2. 锁优化操作

2.1 锁粗化

概念:⼀段逻辑中如果出现多次加锁解锁操作,JVM会⾃动进⾏锁的粗化.

例如: 在公司业务当中,涉及多段方法的调用,每个方法都有加锁解锁操作,但是这多段方法之间并没有其他操作,可以在第一段方法前加锁,最后一段方法解锁,其中的其他方法不涉及加锁解锁操作

在这里插入图片描述

实际开发过程中,使用细粒度锁,是期望释放锁的时候其他线程能使用锁.
但是实际上可能并没有其他线程来抢占这个锁.这种情况JVM就会自动把锁粗化,避免频繁申请释放锁.

把方法级别的细粒度锁,粗化成业务级别的粗粒度锁

2.2 锁消除

概念:JVM判断锁是否可消除.如果可以,就直接消除.

解释: 锁消除是synchronized的一种优化策略
程序员写代码的时候,什么时加synchronized,什么不加,JVM管不了,但是代码在编译运行的时候JVM可以知道加了synchronized的代码是对变量读还是写,还知道当前是多线程状态还是单线程状
如果加了synchronized的代码,并没有对变量进行写操作,那么synchronized对应的锁就不会生效(不会被编译成LOCK)
线程安全问题只有多个线程对同一个共享变量进行写操作时才会发生,如果没有写操作,那么
synchronized就没有必要 ,所有JVM不会真正的去加锁,这个现象叫做锁消除
只有JVM100%确定没有问题的时候才会执行锁消除操作,并不一定所有的代码都会发生

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

StringBuffer sb = new StringBuffer();
 sb.append("a");
 sb.append("b");
 sb.append("c");
 sb.append("d");

在这里插入图片描述

此时每个append的调用都会涉及加锁和解锁.但如果只是在单线程中执行这个代码,那么这些加锁解锁操作是没有必要的,白白浪费了一些资源开销.

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

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

相关文章

IoTDB 2025 春节值班与祝福

2025 春节快乐 瑞蛇迎吉庆,祥光映华年,2025 春节已近在眼前。社区祝福 IoTDB 的所有关注者、支持者、使用者 2025 新年快乐,“蛇”来运转! IoTDB 团队的春节放假时间为 2025 年 1 月 27 日至 2 月 4 日,1 月 25 日、26…

neo4j-community-5.26.0 install in window10

在住处电脑重新配置一下neo4j, 1.先至官方下载 Neo4j Desktop Download | Free Graph Database Download Neo4j Deployment Center - Graph Database & Analytics 2.配置java jdk jdk 21 官网下载 Java Downloads | Oracle 中国 path: 4.查看java -version 版本 5.n…

matlab中,fill命令用法

在 MATLAB 中,fill 命令用于创建填充多边形的图形对象。使用 fill 可以在二维坐标系中绘制填充的区域,通常用于绘制图形的背景或显示数据分布。 基本语法 fill(X, Y, C)X 和 Y 是同样长度的向量,定义了多边形的顶点坐标。C 是颜色&#xff0…

ThinkPHP 8 操作JSON数据

【图书介绍】《ThinkPHP 8高效构建Web应用》-CSDN博客 《2025新书 ThinkPHP 8高效构建Web应用 编程与应用开发丛书 夏磊 清华大学出版社教材书籍 9787302678236 ThinkPHP 8高效构建Web应用》【摘要 书评 试读】- 京东图书 使用VS Code开发ThinkPHP项目-CSDN博客 编程与应用开…

Java—三种遍历方式

迭代器遍历 特点&#xff1a;迭代器不依赖素引 迭代器使用案例一般在集合中使用 import java.util.ArrayList; import java.util.Collection; import java.util.Iterator;public class text1 {public static void main(String[] args) {Collection<String> collnew Arr…

线性调整器——耗能型调整器

线性调整器又称线性电压调节器&#xff0c;以下是关于它的介绍&#xff1a; 基本工作原理 线性调整器的基本电路如图1.1(a)所示,晶体管Q1(工作于线性状态,或非开关状态)构成一个连接直流源V和输出端V。的可调电气电阻,直流源V由60Hz隔离变压器&#xff08;电气隔离和整流&#…

leetcode——二叉树的最大深度(java)

给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3 示例 2&#xff1a; 输入&#xff1a;root [1,null,2] 输…

K8S中高级存储之PV和PVC

高级存储 PV和PVC 由于kubernetes支持的存储系统有很多&#xff0c;要求客户全都掌握&#xff0c;显然不现实。为了能够屏蔽底层存储实现的细节&#xff0c;方便用户使用&#xff0c; kubernetes引入PV和PVC两种资源对象。 PV&#xff08;Persistent Volume&#xff09; PV是…

IVD设备-GB4793.1 安规理解笔记

IVD设备-GB4793.1 安规理解笔记 参考国标文档 GB4793.1接地电阻试验试验通过的标准 耐压试验试验通过的标准 浮地危险带电部分与可触及导电零部件之间耐压试验通过的标准 参考国标文档 GB4793.1 接地电阻试验 图1GB 4793.1-2007标准 附录F.2 ⌘根据F.1要求内容是关保护接地电…

“AI视频智能分析系统:让每一帧视频都充满智慧

嘿&#xff0c;大家好&#xff01;今天咱们来聊聊一个特别厉害的东西——AI视频智能分析系统。想象一下&#xff0c;如果你有一个超级聪明的“视频助手”&#xff0c;它不仅能自动识别视频中的各种元素&#xff0c;还能根据内容生成详细的分析报告&#xff0c;是不是感觉特别酷…

002-基于Halcon的图像几何变换

本节将简要介绍Halcon中有关图像几何变换的基本算子及其应用&#xff0c;主要涉及五种常见的二维几何变换形式&#xff1a;平移、镜像、旋转、错切和放缩。这几种变换可归结为一类更高级更抽象的空间变换类型&#xff0c;即仿射变换&#xff08;Affine transformation&#xff…

七、深入了解SpringBoot的配置文件

一、配置端口号 通过配置文件application.properties配置修改端口号 修改 application.properties 文件 #端口号修改成 9090 server.port9090运行结果&#xff0c;观察日志 二、配置文件格式 Spring Boot 配置⽂件有以下三种&#xff1a; • application.properties • ap…

【Kubernetes】Pod生命周期、初始化容器、主容器

一、Pod生命周期 Pod从创建到终止退出的时间范围称为Pod生命周期。 1、生命周期重要流程 创建基础容器&#xff08;pause container&#xff09;初始化容器&#xff08;init-X Containers&#xff09;主容器&#xff08;container&#xff09;启动后的钩子(post-start)启动探…

网络爬虫学习:应用selenium获取Edge浏览器版本号,自动下载对应版本msedgedriver,确保Edge浏览器顺利打开。

一、前言 我从24年11月份开始学习网络爬虫应用开发&#xff0c;经过2个来月的努力&#xff0c;于1月下旬完成了开发一款网络爬虫软件的学习目标。这里对本次学习及应用开发进行一下回顾总结。 前几天我已经发了一篇日志&#xff08;网络爬虫学习&#xff1a;应用selenium从搜…

python学opencv|读取图像(四十九)原理探究:使用cv2.bitwise()系列函数实现图像按位运算

【0】基础定义 按位与运算&#xff1a;两个等长度二进制数上下对齐&#xff0c;全1取1&#xff0c;其余取0。 按位或运算&#xff1a;两个等长度二进制数上下对齐&#xff0c;有1取1&#xff0c;其余取0。 按位异或运算&#xff1a; 两个等长度二进制数上下对齐&#xff0c;相…

U盘打开提示格式化:深度解析与数据恢复全攻略

在数字化时代&#xff0c;U盘作为便捷的数据存储和传输工具&#xff0c;广泛应用于各个领域。然而&#xff0c;当我们满怀期待地插入U盘&#xff0c;却遭遇“U盘打开提示格式化”的尴尬局面时&#xff0c;那份焦虑与无助感油然而生。本文将全面剖析U盘打开提示格式化的原因、应…

将5分钟安装Thingsboard 脚本升级到 3.9

稍微花了一点时间&#xff0c;将5分钟安装Thingsboard 脚本升级到最新版本 3.9。 [rootlab5 work]# cat one-thingsboard.shell echo "test on RHEL 8.10 " source /work/java/install-java.shell source /work/thingsboard/thingsboard-rpm.shell source /work/po…

【新春不断更】题海拾贝:P1878 舞蹈课

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》 欢迎点赞&#xff0c;关注&#xff01; 1、题…

Windows 程序设计6:错误码的查看

文章目录 前言一、说明二、使用GetLastError找到错误的原因三、使用错误码的宏总结 前言 Windows 程序设计6&#xff1a;错误码的查看。 一、说明 有时写的代码单纯看是没有问题的&#xff0c;但是执行起来就会崩溃。因此要养成判断函数执行是否成功的习惯&#xff0c;除非这…

[STM32 - 野火] - - - 固件库学习笔记 - - -十三.高级定时器

一、高级定时器简介 高级定时器的简介在前面一章已经介绍过&#xff0c;可以点击下面链接了解&#xff0c;在这里进行一些补充。 [STM32 - 野火] - - - 固件库学习笔记 - - -十二.基本定时器 1.1 功能简介 1、高级定时器可以向上/向下/两边计数&#xff0c;还独有一个重复计…