当前位置: 首页 > news >正文

synchronized进阶原理

synchronized进阶原理

1.轻量级锁

轻量级锁的使用场景:如果一个对象虽然有多个线程访问,但多线程访问的时间是错开的(也就是没有竞争),那么可以使用轻量级锁来优化(如果出现竞争,操作系统会将轻量级锁升级为重量级锁)。轻量级锁对使用者是透明的(由操作系统控制),即语法仍是synchronized。

假设有两个方法同步块,利用同一个对象加锁

static final Object obj = new Object();
public static void method1(){synchronized(obj){//同步块Amethod2();}
}
public static void method2(){synchronized(obj){//同步块B}
}

创建锁记录(Lock Record)对象,每个线程的栈帧都会包含一个锁记录的结构,内部可以存储锁定对象的Mark Word

在这里插入图片描述

让锁记录中Object reference 指向锁对象,并尝试用cas替换Object的Mark Word,将Mark Word的值存入锁记录(01代表未上锁,00代表上轻量级锁)

在这里插入图片描述

如果cas替换成功,对象头中存储了锁记录地址和状态00,表示由该线程给对象加锁

在这里插入图片描述

如果cas失败,有两种情况

· 如果其它线程已经持有了该Object的轻量级锁,这时表明有竞争,进入锁膨胀过程

· 如果是自己执行了synchronized锁重入(自己又对synchronized加锁了),那么再添加一条Lock Record作为重入的计数

在这里插入图片描述

当退出synchronized代码块(解锁时)如果有取值为null的锁记录,表示有重入,这时重置锁记录,表示重入计数减一

在这里插入图片描述

当退出synchronized代码块(解锁时)锁记录的值不为null,这时使用cas将Mark Word的值恢复给对象头

· 成功,则解锁成功

· 失败,说明轻量级锁进行了膨胀或已经升级为重量级锁,进入重量级锁解锁流程

2.锁膨胀

如果在尝试加轻量级锁的过程中,CAS操作无法成功,这时一种情况就是有其他线程为此对象加上了轻量级锁(有竞争),这时需要进行锁膨胀,将轻量级锁变为重量级锁。

static Object obj = new Object();
public static void method1(){synchronized(obj){//同步块}
}

当Thread-1进行轻量级锁时,Thread-0已经对该对象加了轻量级锁

在这里插入图片描述

这时Thread-1加轻量级锁失败,进入锁膨胀流程

· 即为Object对象申请Monitor锁,让Object指向重量级锁地址

· 然后自己进入Monitor的EntryList中 BLOCKED

在这里插入图片描述

当Thread-0退出同步代码块解锁时,使用cas将Mark Word的值恢复给对象头,失败。这时会进入重量级解锁流程,即按照Monitor地址找到Monitor对象,设置Owner为null,唤醒EntryList中BLOCKED线程,从它们中竞争出下一个与Owner关联的线程

3.自旋优化

重量级锁竞争的时候,还可以使用自旋锁来进行优化,如果当前线程自旋锁成功(即这时候持锁线程已经退出了同步块,释放了锁),这时当前线程就可以避免阻塞。

自选重试成功的情况

在这里插入图片描述

自旋重试失败的情况

在这里插入图片描述

在java6之后自旋锁是自适应的,比如对象刚刚的一次自旋操作成功过,那么认为这次自旋成功的可能性会高,就多自旋几次;反之,就少自旋甚至不自旋。自旋会占用CPU时间,单核CPU自旋就是浪费,多核CPU自旋才能发挥优势。java7之后不能控制是否开启自旋功能。

4.偏向锁

轻量级锁在没有竞争时(就自己这个线程),每次重入仍需要执行CAS操作。java6中引入了偏向锁来做进一步优化:只有第一次使用CAS将线程ID设置到对象的Mark Word头,之后发现这个线程ID是自己的就表示没有竞争,不用重新CAS。以后只要不发生竞争,这个对象就归该线程所有。

static final Object obj = new Object();
public static void m1(){synchronized(obj){//同步块Am2();}
}
public static void m2(){synchronized(obj){//同步块Bm3();}
}
public static void m3(){synchronized(obj){//同步块C}
}

在这里插入图片描述

在这里插入图片描述

偏向状态

对象头:

在这里插入图片描述

biased_lock 用于记录是否启动偏向锁(0为未启动)

thread 是线程id(操作系统给的,和java中自己设置的不同)

一个对象创建时:

· 如果启动了偏向锁(默认开启),那么对象创建后,markword值为0x05即最后3位为101,这时它的thread、epoch、age都是0

· 偏向锁默认是延迟的,不会在程序启动时立即生效,如果想避免延迟,可以加VM参数 - XX:BiasedLockingStartupDelay=0来禁止延迟

· 如果没有开启偏向锁,那么对象创建后,markword值为0x01即最后3位为001,这时它的hashcode、age都为0,第一次用到hashcode时才会赋值

测试禁用:在上面测试代码运行时在添加VM参数 -XX: -UseBiasedLocking 禁用偏向锁

测试hashCode:当对用对象的hashCode()时,偏向锁会被撤销,对象就会变成普通状态(当轻量级锁对象调用hashCode()时,hashCode会记录在栈帧中的锁记录里,当重量级锁调用hashCode()时,hashCode会存在monitor对象里)

撤销偏向锁-其它线程使用对象

当有其他线程使用偏向锁对象时,会将偏向锁升级为轻量级锁。

撤销偏向锁-使用wait/notify

批量重偏向

如果对象虽然被多个线程访问,但没有竞争,这时偏向了线程T1的对象仍有机会重新偏向T2,重偏向会重置对象的Thread ID

当撤销偏向锁阈值超过20次后,JVM会在给这些对象加锁时重新偏向至加锁线程。

批量撤销

当撤销偏向锁阈值超过40次后,JVM会觉得不该偏向。于是整个类的所有对象都会变为不可偏向的,新建的对象也是不可偏向的。

锁撤销

java有即时编译器(JIT),会对代码进行优化,将一些无用的锁优化掉了

相关文章:

synchronized进阶原理

synchronized进阶原理 1.轻量级锁 轻量级锁的使用场景:如果一个对象虽然有多个线程访问,但多线程访问的时间是错开的(也就是没有竞争),那么可以使用轻量级锁来优化(如果出现竞争,操作系统会将轻量级锁升级为重量级锁)。轻量级锁对使用者是透明的(由操作系统控制),即语法仍是s…...

C++,STL 052(24.10.29)

内容 1.对map容器的大小进行操作。 2.map容器的交换操作。 运行代码 #include <iostream> #include <map>using namespace std;void printMap(map<int, int> &m) {for (map<int, int>::iterator it m.begin(); it ! m.end(); it){cout <<…...

git下载和配置

git是什么&#xff1f; Git是一种分布式版本控制系统&#xff0c;用于跟踪文件的变化&#xff0c;尤其是源代码。它允许多个开发者在同一项目上进行协作&#xff0c;同时保持代码的历史记录。Git的主要特点包括&#xff1a; 分布式&#xff1a;每个开发者都有项目的完整副本&a…...

Linux基础—基础命令及相关知识5(ubuntu网络配置)

网络的配置方法 centos网络配置 centos的网卡位置 /etc/sysconfig/network-scripts/ifcfg-ens33(centos网卡文件) bootproto表示获得IP地址的方式是静态的还是动态 onboot表示启动系统时是否激活该网络接口 设置IP地址&#xff0c;子网掩码&#xff0c;网关&#xff0c;dns…...

使用 firewall-cmd 管理 Linux 防火墙

firewalld-cmd命令翻译<一> Linux 系统中&#xff0c;firewalld 是一个流行的动态防火墙管理工具&#xff0c; firewall-cmd 是它的命令行接口。通过 firewall-cmd&#xff0c;可以轻松地管理防火墙规则、配置区域&#xff08;zones&#xff09;、处理端口等。 这篇文章…...

鸿蒙OS试题

哪些是持续部署最佳实践? A. 灰度发布:先在小部分用户或区域进行部署&#xff0c;观察没问题后再全面推广 B.手工部署:持续部署可以采用手工部署的方式发布软件: 1、有一份非常详尽的文档&#xff0c;该文档描述了执行步骤及每个步骤中易出错的地方; 2、以手工测试来确认该…...

Flutter InkWell组件去掉灰色遮罩

当InkerWell组件内部获取到焦点时&#xff0c;会展示一层灰色遮罩 将focusColor属性设置为透明即可 Flutter InkWell焦点效果源码分析 问题描述 当 InkWell 组件获得焦点时&#xff0c;会显示一层灰色遮罩效果。需要找出这个效果是由哪些组件控制的&#xff0c;以及具体的…...

Android——metaData

获取元数据信息的步骤&#xff1a; 调用 getPackageManager 方法获得当前应用的包管理器调用包管理器的 getActivityInfo 方法获得当前活动的信息对象活动信息对象的 metaData 是 Bundle 包裹类型&#xff0c;调用包裹对象的 getString 即可获得指定名称的参数值 配置 metaDa…...

SLAM|1. 相机投影及相机畸变

一个能思考的人&#xff0c;才真是一个力量无边的人。——巴尔扎克 本章主要内容&#xff1a; 1.针孔相机模型 2.相机成像的几个坐标系图像 3.畸变及相机标定 本节主要介绍在照相机拍摄过程中&#xff0c;现实物体如何跟照片上的像素关联起来&#xff0c;具体涉及相机成像的物…...

nginx配置及虚拟主机

nginx配置及虚拟主机 一、http协议介绍1、网站类型2、涉及的软件3、http协议介绍 二、nginx安装、启动1、nginx介绍2、nginx安装3、nginx启动管理 三、nginx配置文件1、配置文件语法结构2、全局配置3、事件驱动模型的配置4、http的配置 四、虚拟主机配置1、类型2、基于名称的虚…...

ElasticSearch - Bucket Script 使用指南

文章目录 官方文档Bucket Script 官文1. 什么是 ElasticSearch 中的 Bucket Script&#xff1f;2. 适用场景3. Bucket Script 的基本结构4. 关键参数详解5. 示例官方示例&#xff1a;计算每月 T 恤销售额占总销售额的比率百分比示例计算&#xff1a;点击率 (CTR) 6. 注意事项与…...

Android的SQLiteOpenHelper类 笔记241027

SQLiteOpenHelper SQLiteOpenHelper是Android开发中用于管理SQLite数据库的一个非常重要的工具类。以下是对SQLiteOpenHelper的详细介绍&#xff1a; 一、基本概念 SQLiteOpenHelper是一个抽象类&#xff0c;它主要用于管理数据库的创建和版本管理。通过继承这个类&#xff…...

「Mac畅玩鸿蒙与硬件10」鸿蒙开发环境配置篇10 - 项目实战:计数器应用

本篇将通过一个简单的计数器应用,带你体验鸿蒙开发环境的实际操作流程。本项目主要练习组件的使用、事件响应和状态管理,帮助开发者熟悉基本的应用构建流程。 关键词 计数器应用组件操作事件响应状态管理HarmonyOS 应用开发一、创建计数器项目 1.1 在 DevEco Studio 中新建项…...

安卓逆向之ARM汇编寻址,汇编指令

一&#xff1a;ARM汇编寻址 1. 立即数寻址 (Immediate Addressing) 指令中直接给出一个常数值&#xff08;立即数&#xff09;&#xff0c;并对其进行操作。 MOV R0, #5 ; 将立即数5载入寄存器R02. 直接寻址 (Direct Addressing) 指令中给出的地址直接指定了内存中的一…...

Idea常见插件(超级实用)

文章目录 Idea好用的插件推荐Idea插件安装Chinese(中文版)Alibaba Java Coding Guidelines&#xff08;代码规范&#xff09;Auto Filling Java Arguments&#xff08;自动补全参数&#xff09;CamelCase&#xff08;变量名称格式转换&#xff09;CodeGeeX&#xff08;智能&…...

C++中如何获取时间并格式化为字符串?

在C中&#xff0c;你可以使用标准库中的 <chrono> 和 <iomanip> 头文件来获取当前时间并将其格式化为字符串。以下是一个简单的示例&#xff0c;展示了如何获取当前时间并将其格式化为一个可读的字符串&#xff08;例如&#xff1a;YYYY-MM-DD HH:MM:SS&#xff09…...

项目1 yolov5鱼苗检测计数

yolov5鱼苗检测 1. yolov5鱼苗检测1.1. 环境配置1.2 Predict1.3 Validate1.4 Train1.5 生成 ONNX 2 代码解析2.1 模型2.2 数据集2.3 损失函数2.4 训练2.5 预测 之前做的项目&#xff0c;再回顾一下 环境&#xff1a;GPU1卡&#xff0c;CPU4核&#xff0c;每显卡12GB&#xff0c…...

GPU 学习笔记三:GPU多机多卡组网和拓扑结构分析(基于数据中心分析)

文章目录 一、概述二、数据中心&#xff08;DC&#xff09;2.1 数据中心简介2.2 传统数据中心的网络模型2.3 脊叶网络模型&#xff08;Spine-Leaf&#xff09;2.4 Facebook的Fabric网络架构 三、基于数据中心的多机多卡拓扑3.1 Spine-Leaf 架构网络规模测算方法3.2 NVIDIA多机多…...

各编程语言处理HTTP状态码的库推荐

Http 状态码用那个库 备注 Spring 的状态码库为 org.springframework.http.HttpStatus Apache 的状态码库为&#xff1a; org.apache.http.HttpStatus 通常这 2 个库都差不多。 如你的项目中已经用了 Spring 的代码的话&#xff0c;那么就用 Spring 的库吧。 不管是那个库…...

【Mac】Python 环境管理工具

一、pyenv 1、安装 &#xff08;1&#xff09;安装 brew install pyenv&#xff08;2&#xff09;环境配置 查看系统使用 shell 是 bash 还是 zsh bash 配置文件&#xff1a;~/.bash_profile zsh 配置文件&#xff1a;~/.zshrc userMac ~ % echo $SHELL /bin/zsh userMa…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...