【JUC】二十八、synchronized锁升级之偏向锁

文章目录

  • 1、偏向锁出现的背景
  • 2、从共享对象的内存结构看偏向锁
  • 3、偏向锁的持有
  • 4、启动偏向锁
  • 5、sleep暂停来启动偏向锁
  • 6、偏向锁的撤销
  • 7、总体流程
  • 8、SinceJava15 偏向锁的废除

在这里插入图片描述

1、偏向锁出现的背景

如果一个线程连续几次抢到锁,仍然重复加锁解锁,就会导致用户态和内核态频繁切换,这显然是有改进空间的。如之前买票的例子:

public class SaleTick {public static void main(String[] args) {Ticket ticket = new Ticket();new Thread(() -> {for (int i = 0; i < 50; i++) {ticket.sale();}},"t1").start();new Thread(() -> {for (int i = 0; i < 50; i++) {ticket.sale();}},"t2").start();new Thread(() -> {for (int i = 0; i < 50; i++) {ticket.sale();}},"t3").start();}
}//资源类
class Ticket {private int number = 50;Object lockObject = new Object();public void sale() {synchronized (lockObject) {if (number > 0) {System.out.println(Thread.currentThread().getName() + "卖出票,剩余票数" + number--);}}}
}

发现一个线程一直在抢到锁:

在这里插入图片描述

Hotspot 的作者发现,大多数情况下:多线程的情况下,锁不仅不存在多线程竞争,还存在锁由同一个线程多次获得的情况,偏向锁就是在这种情况下出现的,它的出现是为了解决只有在一个线程执行同步代码块时提高性能。

偏向锁会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他的线程访问,则持有偏向锁的线程将永远不需要触发同步。也即偏向锁在资源没有竞争情况下消除了同步语句,懒的连CAS操作都不做了,直接提高程序性能。

举个例子:生活中,第一次去店铺A吃牛肉汤,老板会问你的口味,然后接下来几天,天天都去吃这家店,那老板以后看到来的是你,就不会再问了,直接给你按口味做就是了。

2、从共享对象的内存结构看偏向锁

从对象结构来看,偏向锁时,被锁对象请求头Mark word的前54位都存当前线程的指针,末尾的三位则改成了101,即代表偏向锁。

在这里插入图片描述

3、偏向锁的持有

当线程A第一次竞争到对象锁时,修改共享对象Mark Word里的偏向线程ID,在没有其他线程竞争的情况下,后续这个线程再进入这个同步代码块时,不需要再次加锁解锁,只需判断对象Mark Word里的ID是不是指向自己

  • 是,就直接执行,且直到有其他线程过来发生竞争才释放锁
  • 不是,说明发生了竞争,就尝试通过CAS修改Mark Word里的线程ID为自身ID

上面CAS时:

  • 如果修改成功,说明线程B来改时,之前偏向的线程A刚结束,此时,仍为偏向锁,偏向B
  • 如果修改失败,升级轻量锁,保证所有线程重新公平竞争

注意点:偏向锁只有遇到其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁,线程是不会主动释放偏向锁的

在这里插入图片描述

偏向锁的操作不会直接捅到操作系统,不涉及用户到内核来回转换。以自定义的Account对象的对象头为例:

在这里插入图片描述

此时,线程A执行到synchronized同步代码块时,JVM通过CAS操作把线程指针ID记录到Account对象的Mark word 中,并修改偏向标识,线程A获得锁成功。注意,执行完同步代码块后,锁并未释放,等线程A二次来时,JVM判断account的Mark Word里面是否还有线程A的ID,有,就继续执行,因为之前没有释放锁,这里自然不用重新获取锁,也就不涉及用户态和内核态的来回切换

在这里插入图片描述

4、启动偏向锁

终端执行以下,查看偏向锁的配置信息:

java -XX:+PrintFlagsInitial | grep BiasedLock*

可以看到偏向锁默认打开,以及启动偏向锁的延迟时长(默认延迟4秒,我这里JDK版本较高,不是4)

在这里插入图片描述

写实例Demo:

在这里插入图片描述

可以看到只有一个线程在操作对象o ⇒ 应该是偏向锁 ⇒ 却发现是轻量锁000

在这里插入图片描述

这是因为偏向锁延时4秒开启,期间自然是下一级:轻量锁。

偏向锁在JDK1.6之后就默认开启,但启动时间有延迟,想立刻启动,可通过添加JVM参数将延迟改为0:

  • -XX:+UseBiasedLocking 开启偏向锁
  • -XX:-UseBiasedLocking 关闭偏向锁,此时会直接跳入轻量锁
  • -XX:BiasedLockingStartupDelay=0 关闭延迟

添加JVM参数,这里关闭延时,正常显示101,即偏向锁:

在这里插入图片描述

5、sleep暂停来启动偏向锁

除了以上添加JVM参数关闭延时来立刻启动偏向锁,也可通过另一种方式:程序执行前等4秒,以保证开启了偏向锁

在这里插入图片描述

再对比下,偏向锁开启后,使用synchronized锁时的对象o和不使用synchronized时的对象o的区别:

在这里插入图片描述

可以看到二者锁状态均为101,但前面o对象未使用synchronized锁,所以线程ID为空,而后者则带了线程ID。

6、偏向锁的撤销

共享对象o的Mark Word一直指向线程A的ID,线程A也一直拿着这个对象锁。直到第二个线程开始来抢夺锁时,线程A的好日子结束:

  • 偏向锁使用一种等到竞争出现才释放锁的机制,只有当其他线程竞争锁时,持有偏向锁的原来线程才会被撤销。

  • 且撤销需要等待全局安全点(该时间点上没有字节码正在执行),同时检查持有偏向锁的线程是否还在执行(客人还在你店里吃饭,你总不能一到打烊时机就掀桌子)

    在这里插入图片描述

  • 如果第一个线程正在执行synchronized方法(处于同步块),它还没有执行完,其它线程来抢夺,该偏向锁会被取消掉并出现锁升级(升级为轻量锁),且此时轻量级锁由原持有偏向锁的线程持有,继续执行其同步代码,而正在竞争的线程会进入自旋等待获得该轻量级锁

  • 第一个线程执行刚好完成synchronized方法(退出同步块),则将对象头设置成无锁状态并撤销偏向锁,重新偏向。直白说就是,另一线程t2来竞争时,偏向的线程t1刚好执行完,那大家就重新竞争。当然,也有可能t1出代码块后,run方法结束,直接走了,那就偏向t2就行

7、总体流程

在这里插入图片描述

8、SinceJava15 偏向锁的废除

JDK15:Disable and Deprecate Biased Locking.
//2020.9.15

Prior to JDK 15, biased locking is always enabled and available. With this JEP, biased locking will no longer be enabled when HotSpot is started unless -XX:+UseBiasedLocking is set on the command line.

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

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

相关文章

【深度学习】注意力机制(六)

本文介绍一些注意力机制的实现&#xff0c;包括MobileVITv1/MobileVITv2/DAT/CrossFormer/MOA。 【深度学习】注意力机制&#xff08;一&#xff09; 【深度学习】注意力机制&#xff08;二&#xff09; 【深度学习】注意力机制&#xff08;三&#xff09; 【深度学习】注意…

产品入门第三讲:Axure产品流程图绘制

&#x1f4da;&#x1f4da; &#x1f3c5;我是默&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; ​​​​​ &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《Axure》。&#x1f3af;&#x1f3af; &#x1f680;无论你是编程小白&#xff0c;还…

机器人行业数据闭环实践:从对象存储到 JuiceFS

JuiceFS 社区聚集了来自各行各业的前沿科技用户。本次分享的案例来源于刻行&#xff0c;一家商用服务机器人领域科技企业。 商用服务机器人指的是我们日常生活中常见的清洁机器人、送餐机器人、仓库机器人等。刻行采用 JuiceFS 来弥补对象存储性能不足等问题。 值得一提的是&am…

Docker容器如何优雅地访问宿主机网络

# 前言 某些时候&#xff0c;我们会有在容器内容访问宿主机某个服务的需求&#xff0c;比如现在 openai 无法直接访问&#xff0c;需要给项目添加代理&#xff0c;我的 chatgpt-dingtalk (opens new window) 项目支持了通过环境变量指定代理地址。 添加方式如下&#xff1a; …

嵌入式奇妙之旅:Python与树莓派编程深度探索

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在这个数字化的时代&#xff0c;嵌入式系统的应…

主动学习与弱监督学习

人工智能数据的获取没有想象中的那么简单&#xff0c;虽然我们早已身处大数据的浪潮下&#xff0c;很多公司在获取数据的大浪中翻滚却始终没有找到一个合适的获取数据的渠道。很多情况下&#xff0c;获取高质量的人工智能数据需要消耗大量的人力、时间、金钱&#xff0c;但是对…

Vue3-08-条件渲染-v-if 的基本使用

v-if 是什么 v-if 一个指令&#xff0c; 它是用来根据条件表达式&#xff0c;进行选择性地【展示】/【不展示】html元素的。比如 &#xff1a; 有一个按钮A&#xff0c;当条件为真时&#xff0c;展示该按钮&#xff1b;条件为假时&#xff0c;不展示该按钮。与 js 中的 条件判…

绝地求生:PGC2023胜者组D2下半场:17天霸成功晋级,TL、NH跌入最后机会组

第四场 第一名&#xff1a;LGC 第二名&#xff1a;T5 第三名&#xff1a;FaZe 17仅剩两人&#xff0c;T5踩住高点&#xff0c;sujiu前顶时被T5架枪位击倒&#xff0c;小鬼的盾牌没能挡住对方的雷遗憾第五出局。然而T5自己也进圈不易&#xff0c;仅剩两人。 LG独狼卡住T5却忽…

Leetcode 2132. 用邮票贴满网格图(Java + 两次一维前缀和 + 二维差分)

Leetcode 2132. 用邮票贴满网格图&#xff08;Java 两次一维前缀和 二维差分&#xff09; 题目 给你一个 m x n 的二进制矩阵 grid &#xff0c;每个格子要么为 0 &#xff08;空&#xff09;要么为 1 &#xff08;被占据&#xff09;。给你邮票的尺寸为 stampHeight x sta…

Linux_Ubuntu 系统入门

Ubuntu 系统是和 Windows 系统一样的大型桌面操作系统&#xff0c;因此功能非常强大。 本节的目的是掌握后续嵌入式开发所需的 Ubuntu 基本技能&#xff0c;比如系统的基本设置、常用的 shell 命令、vim 编译器的基本操作等等…… Ubuntu 的图形化界面操作和 Windows 下基本一致…

数据分析基础之《matplotlib(3)—散点图》

一、常见图形种类及意义 1、matplotlib能够绘制折线图、散点图、柱状图、直方图、饼图。我们需要知道不同的统计图的意义&#xff0c;以此来决定选择哪种统计图来呈现我们的数据 2、折线图plot 说明&#xff1a;以折线的上升或下降来表示统计数量的增减变化的统计图 特点&…

智能优化算法应用:基于白鲸算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于白鲸算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于白鲸算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.白鲸算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

实践干货 | CodeWave如何支持多人协作开发应用

在传统软件开发领域里&#xff0c;要完成具备一定复杂程度的软件&#xff0c;通常都会由一个研发团队协作开发。软件复杂度越大&#xff0c;研发团队的规模也就越大。 为了让研发团队能够高效的进行协同开发&#xff0c;业务引入了优秀的代码版本管理工具&#xff0c;比如传统软…

C语言union联合体(共用体)

一、定义 联合体&#xff08;共用体&#xff09;是一种特殊的自定义的数据类型&#xff0c;它包含一系列的成员变量&#xff0c;这些成员变量共用一块内存空间。 语法&#xff1a; union 标识符 { data_type 标识符1; data_type 标识符2; . . . dat…

【数组Array】力扣-5 最长回文子串

目录 题目描述 题解labuladong 题目描述 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同&#xff0c;则该字符串称为回文字符串。 示例 1&#xff1a; 输入&#xff1a;s "babad" 输出&#xff1a;"bab"…

在javaweb项目中resource目录和webapp目录的区别

resource存放的是一些配置文件&#xff0c;这些文件一般都是与java代码相关的配置文件&#xff0c;比如这里的jdbc配置文件,在java中可以使用这个目录下的文件&#xff0c;不用写全路径 webapp存放的是web的资源文件&#xff0c;如jsp,html,css&#xff0c;js文件,在网页请求会…

【NSX-T】5. 搭建NSX-T环境 —— NSX架构基础配置

目录 5. 准备 NSX 基础架构5.1 准备工作5.2 创建传输域&#xff08;1&#xff09;创建 Overlay 传输域&#xff08;2&#xff09;创建 VLAN 传输域 5.3 创建 IP 池5.4 准备 ESXi 主机 参考资料 5. 准备 NSX 基础架构 5.1 准备工作 vCenter 中已存在 DVS。 为 NSX-T 创建两个 …

计算机毕业设计 基于Web的城市旅游网站的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

ARM I2C通信

1.概念 I2C总线是PHLIPS公司在八十年代初推出的一种串行的半双工同步总线&#xff0c;主要用于连接整体电路2.IIC总线硬件连接 1.IIC总线支持多主机多从机&#xff0c;但是在实际开发过程中&#xff0c;大多数采用单主机多从机模式 2.挂接到IIC总线上&#xff0c;每个从机设备都…

现代雷达车载应用——第2章 汽车雷达系统原理 2.4节 雷达波形和信号处理

经典著作&#xff0c;值得一读&#xff0c;英文原版下载链接【免费】ModernRadarforAutomotiveApplications资源-CSDN文库。 2.4 雷达波形和信号处理 对于连续波雷达来说&#xff0c;波形决定了其基本信号处理流程以及一些关键功能。本节将以FMCW波形为例&#xff0c;讨论信号…