一文带你了解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, 挂电话
显然, 方式二是更高效的方案。

 


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

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

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

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

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

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

 

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

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

相关文章

分享Python给自己写的函数添加注释的小功能

def get_ips(prefix: str, suffix: int) -> List[str]:"""获取 IP 地址段。Args:prefix: IP 地址的前缀。suffix: IP 地址的后缀。Returns:IP 地址列表。"""... """ """ 就是注释开始以及注释结束。 效果&a…

C语言学习笔记之数组篇

数组是一组相同类型元素的集合。 目录 一维数组 数组的创建 数组的初始化 数组的使用 数组在内存中的存储 二维数组 数组的创建 数组的初始化 数组的使用 数组在内存中的存储 数组名 数组名作函数参数 一维数组 数组的创建 type_t arr_name [const_n]; //type_…

华为 ArkTS 边框怎么设置,单边边框怎么设置以及条件设置边框(鸿蒙开发)

一、实例代码: border(params) 接收一个对象参数,对象参数的属性为width?: Lenght,color?: ,radius?: Length,style?: BorderStyle 注意:以下实例包含了我说知道的 边框的单位 以及 颜色 的各种用法 Column() {Im…

【独家OD2023C卷真题】20天拿下华为OD笔试【二分查找】2023C-部门人力分配【欧弟算法】全网注释最详细分类最全的华为OD真题题解

题目描述与示例 题目描述 部门在进行需求开发时需要进行人力安排。当前部门需要完成 N 个需求,需求用 requirements[i] 表示,requirements[i] 表示第 i 个需求的工作量大小,单位:人月。这部分需求需要在 M 个月内完成开发&#…

【已解决】MySQL:执行存储过程报错(MySQL字符集和排序方式冲突)

目录 问题现象: 问题分析: 解决方法: 拓展: 1、转换条件两边的字段或值为二进制数据: 2、转换条件两边的字段或值的字符集和排序方式: 3、修改列、表、库的字符集和排序方式 参考链接: 问…

spring webflux文件上传与下载

1、文件上传: Controller: PostMapping("/import")public void importImage(RequestPart("file") FilePart filePart) {imageService.importImage(filePart);}Service: public void importImage(FilePart filePart) {Fi…

java之arraylist的用法

java之arraylist的用法 Java中的ArrayList是一种基于动态数组实现的List接口。它允许使用索引访问和操作元素&#xff0c;并提供了高效的插入、查找和删除操作。 以下是关于Java ArrayList的详细用法介绍&#xff1a; 1&#xff09;创建ArrayList对象&#xff1a; List<S…

微信商城小程序怎么制作?做一个小程序需要什么流程?

小程序商城对商家有哪方面的帮助&#xff1f; 随着移动互联网的快速发展&#xff0c;小程序商城已经成为了越来越多商家的选择。那么&#xff0c;小程序商城到底对商家有哪些方面的帮助呢&#xff1f; 一、提高商家曝光度 在小程序平台上开设自己的小程序商城&#xff0c;可以…

AI之火是如何燎原的?始于马斯克与佩奇的一场激辩

丨划重点 ①在2015年, 马斯克44岁生日派对上&#xff0c;他与谷歌联合创始人佩奇曾就AI产生严重分歧&#xff0c;甚至终结了十多年的友谊。佩奇认为人类最终将与AI机器融合&#xff0c;将会有许多种智能争夺资源, 马斯克则担心机器可能会毁灭人类。 ②在收购AI创企DeepMind时…

acwing1209.带分数暴力与优化(java版)

//n a b / c n是确定的,只需找到其中两个。判断剩下一个数是否满足条件即可 //由题目条件可知,每个数不能重复使用,需要一个st全局数组判断每个数是否使用过 //递归实现排列型枚举,cn ac b //对于枚举出来的每一个a,再去枚举每一个c,再在c的枚举里判断b是否满足条件 //…

人工智能学习3(特征变换:特征数值化)

编译工具&#xff1a;PyCharm 有些编译工具不用写print可以直接将数据打印出来&#xff0c;pycharm需要写print才会打印出来。 文章目录 编译工具&#xff1a;PyCharm 概念1.特征类型分类型二值型顺序型数值型 2.特征数值化练习13.特征数值化练习24.特征二值化使用sklearn库自…

day69

今日回顾 Django与Ajax 一、什么是Ajax AJAX&#xff08;Asynchronous Javascript And XML&#xff09;翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互&#xff0c;传输的数据为XML&#xff08;当然&#xff0c;传输的数据不只是XML,现在…

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

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

三个角度(握手、挥手、传输)优化TCP

TCP 三次握手的性能提升 客户端的优化 当客户端发起 SYN 包时&#xff0c;可以通过 tcp_syn_retries 控制其重传的次数。 服务端的优化 当服务端 SYN 半连接队列溢出后&#xff0c;会导致后续连接被丢弃&#xff0c;可以通过 netstat -s 观察半连接队列溢出的情况&#xff0c;如…

【Java GUI 窗体开发实践】基于抽象模板设计模式下实现Windows SSH连接Linux服务器

系列文章目录 文章目录 系列文章目录一、项目实现功能二、使用步骤1.引入抽象类模板2.子类实现具体业务一、项目实现功能 Java GUI 本地输入需要连接的虚拟机 ip地址、端口号、用户名和密码就可以连接上主机。 后续基于SFTP协议传输文件到虚拟机或者在虚拟机上的文件更改,本地…

对标Gen-2!Meta发布新模型进军文生视频赛道

随着扩散模型的飞速发展&#xff0c;诞生了Midjourney、DALLE 3、Stable Difusion等一大批出色的文生图模型。但在文生视频领域却进步缓慢&#xff0c;因为文生视频多数采用逐帧生成的方式,这类自回归方法运算效率低下、成本高。 即便使用先生成关键帧,再生成中间帧新方法。如…

在线客服系统有哪些?如何选择呢?

当我们谈论在线客服系统时&#xff0c;我们可能会面临着一系列的问题和疑惑&#xff0c;比如&#xff1a; 在线客服系统有哪些&#xff1f; 如何选择合适的在线客服系统&#xff1f; 首先&#xff0c;让我们看看目前市场上存在的在线客服系统。这些系统包括但不限于&#xff1a…

Windows下使用AndroidStudio及CMake编译Android可执行程序或静态库动态库

Windows下使用AndroidStudio及CMake编译Android可执行程序或静态库动态库 文章目录 Windows下使用AndroidStudio及CMake编译Android可执行程序或静态库动态库一、前言二、编译环境三、示例C/CPP程序1、总体工程结构2、示例代码3、CMakeLists.txt&#xff08;重要&#xff09;4、…

Python中删除文件和目录

python中分别提供os包下的os.remove()与shutil包下的shutil.rmtree()函数&#xff0c;其中os.remove(&#xff09;的主要作用是删除一个具体的文件&#xff0c;shutil.rmtree()主要作用是删除一个具体的目录。 os.remove() 这个函数需要一个参数&#xff0c;即要删除的文件的…

Python语言基础学习大纲(由某大模型生成)

自从上次经丙察察游了一次滇藏线&#xff0c;已有3个没写一篇了。今天利用由某大模型生成的上面这张思维导图&#xff0c;配合这个大模型生成的6000多字拼凑出一篇博文聊以交差。 Python语言概述 一、语言特点 1.语法简单明了 Python的语法简洁易懂&#xff0c;使得编写代码…