锁升级过程和原理

2023-11-12

目录

锁升级过程和原理

同步方法与一般方法字节码对比

public class SynchronizedTest1 {
    public static void main(String[] args) {
        synchronized (SynchronizedTest1.class){
            int a = 1;
        }
    }
}
0 ldc #2 <SynchronizedTest/SynchronizedTest1>
 2 dup
 3 astore_1
 4 monitorenter//监视器的进入(获取监视器)
 5 iconst_1
 6 istore_2
 7 aload_1
 8 monitorexit
 9 goto 17 (+8)
12 astore_3
13 aload_1
14 monitorexit//监视器的退出(释放监视器)
15 aload_3
16 athrow
17 return

public class SynchronizedTest1 {
    public static void main(String[] args) {
        //synchronized (SynchronizedTest1.class){
            int a = 1;
        //}
    }
}
0 iconst_1
1 istore_1
2 return

线程再获取锁时 实际上就是获取一个监视器对象(monitor)

monitor可以认为是一个同步对象 所有的java对象天生携带monitor

获取monitor的过程即排他的过程

任意时刻只有一个线程能获取到由synchronized保护的对象的监视器

对象头中的锁信息

对象头包括两部分数据
MarkWord 标记字段
klassPointer 类型指针
数组类型还有一个int类型的数组长度

其中MarkWorld记录了对象和锁有关的信息

当这个对象被synchronized关键字当成同步锁使用时
围绕这个锁的一系列操作都于markWorld有关

MarkWorld在32位的JVM中的长度是32位
在64位的JVM中长度是64位

markworld在不同锁的状态下存储的内容不同
示意图如下

在这里插入图片描述

锁升级即jvm随着某对象被线程争抢的剧烈程度增加
对该对象锁的处理从偏向锁→轻量级锁→重量级锁的升级过程

锁升级中涉及的四种锁

  • 无锁 不加锁

  • 偏向锁 只有一个线程争夺时 偏向于某个线程 这个线程访问不加锁

  • 轻量级锁 少量线程争夺时 先尝试自选 不挂起线程

    挂起线程和恢复线程会导致线程内核态到用户态之间的切换 带来额外的性能开销
    让现场执行一个盲循环而不放弃处理器的执行时间
    等待现持有锁的线程释放锁
    即自旋锁

  • 重量级锁 排队挂起线程

锁升级的过程

  1. 当此对象没有被当成锁 markWord记录对象的HashCode
    此时对象为无锁状态
    锁标志位位01 是否偏向锁位为0

  2. 当对象被作为同步锁使用且有一个线程A获得了锁时
    锁标志位还是01是否偏向锁位设为1
    前32位记录获取锁的线程的id

    1. 当线程A再次试图获取锁时 JVM发现同步锁标志位位01偏向锁位为1
      即此对象处于偏向锁状态
      同时检查markword中记录的线程id是否为自己的id
      如果是 可以执行同步锁的代码
  3. 当线程B试图获得锁时 此对象依然为偏向锁状态但其记录的线程id不是B线程的id
    那么B会用CAS操作试图获得锁

    1. 如果获得成功
      线程b将markword中的线程id改为自己的id并执行代码

    2. 如果抢锁失败
      执行下一步骤

  4. 抢锁失败说明此锁有一定竞争
    JVM将此锁升级为轻量锁

    1. 在前线程的线程栈中开辟单独空间 保存指向对象锁的MarkWord
      称为锁记录LockRecord

    2. 同时在对象锁markWord中保存指向这篇空间的指针

    3. 上面两个cas操作都为cas操作 如果保存成功说明抢到了锁
      将markWord中的标志位改为00
      可以执行同步锁代码

    4. 如果保存失败 代表抢锁失败 执行下一步骤

  5. 轻量级锁抢锁失败 JVM会使用自旋锁 即不断重试抢锁
    默认自旋次数为10次
    如果10次后依然失败 进行下一步骤

  6. 升级为重量锁
    锁的标志位改为10
    此状态下 未抢到锁的线程会被阻塞排队
    当后续线程尝试获取锁时
    如果锁已被占用 且发现其为重量级锁
    则直接将自己阻塞挂起
    等待将来被唤醒

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

锁升级过程和原理 的相关文章

  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • Spring Batch 多线程 - 如何使每个线程读取唯一的记录?

    这个问题在很多论坛上都被问过很多次了 但我没有看到适合我的答案 我正在尝试在我的 Spring Batch 实现中实现多线程步骤 有一个包含 100k 条记录的临时表 想要在 10 个线程中处理它 每个线程的提交间隔为 300 因此在任何时
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • 控制Android的前置LED灯

    我试图在用户按下某个按钮时在前面的 LED 上实现 1 秒红色闪烁 但我很难找到有关如何访问和使用前置 LED 的文档 教程甚至代码示例 我的意思是位于 自拍 相机和触摸屏附近的 LED 我已经看到了使用手电筒和相机类 已弃用 的示例 但我
  • Java TestNG 与跨多个测试的数据驱动测试

    我正在电子商务平台中测试一系列商店 每个商店都有一系列属性 我正在考虑对其进行自动化测试 是否有可能有一个数据提供者在整个测试套件中提供数据 而不仅仅是 TestNG 中的测试 我尝试不使用 testNG xml 文件作为机制 因为这些属性
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • 如何在 javadoc 中使用“<”和“>”而不进行格式化?

    如果我写
  • 如何在控制器、服务和存储库模式中使用 DTO

    我正在遵循控制器 服务和存储库模式 我只是想知道 DTO 在哪里出现 控制器应该只接收 DTO 吗 我的理解是您不希望外界了解底层域模型 从领域模型到 DTO 的转换应该发生在控制器层还是服务层 在今天使用 Spring MVC 和交互式
  • 仅将 char[] 的一部分复制到 String 中

    我有一个数组 char ch 我的问题如下 如何将 ch 2 到 ch 7 的值合并到字符串中 我想在不循环 char 数组的情况下实现这一点 有什么建议么 感谢您花时间回答我的问题 Use new String value offset
  • Java列表的线程安全

    我有一个列表 它将在线程安全上下文或非线程安全上下文中使用 究竟会是哪一个 无法提前确定 在这种特殊情况下 每当列表进入非线程安全上下文时 我都会使用它来包装它 Collections synchronizedList 但如果不进入非线程安
  • 编译器抱怨“缺少返回语句”,即使不可能达到缺少返回语句的条件

    在下面的方法中 编译器抱怨缺少退货声明即使该方法只有一条路径 并且它包含一个return陈述 抑制错误需要另一个return陈述 public int foo if true return 5 鉴于Java编译器可以识别无限循环 https
  • 在 Maven 依赖项中指定 jar 和 test-jar 类型

    我有一个名为 commons 的项目 其中包含运行时和测试的常见内容 在主项目中 我添加了公共资源的依赖项
  • JGit 检查分支是否已签出

    我正在使用 JGit 开发一个项目 我设法删除了一个分支 但我还想检查该分支是否已签出 我发现了一个变量CheckoutCommand但它是私有的 private boolean isCheckoutIndex return startCo
  • 将 List 转换为 JSON

    Hi guys 有人可以帮助我 如何将我的 HQL 查询结果转换为带有对象列表的 JSON 并通过休息服务获取它 这是我的服务方法 它返回查询结果列表 Override public List
  • 按日期对 RecyclerView 进行排序

    我正在尝试按日期对 RecyclerView 进行排序 但我尝试了太多的事情 我不知道现在该尝试什么 问题就出在这条线上适配器 notifyDataSetChanged 因为如果我不放 不会显示错误 但也不会更新 recyclerview
  • 如何实现仅当可用内存较低时才将数据交换到磁盘的写缓存

    我想将应用程序生成的数据缓存在内存中 但如果内存变得稀缺 我想将数据交换到磁盘 理想情况下 我希望虚拟机通知它需要内存并将我的数据写入磁盘并以这种方式释放一些内存 但我没有看到任何方法以通知我的方式将自己挂接到虚拟机中before an O
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j

随机推荐

  • 数据双向绑定

    一 什么是双向绑定 我们先从单向绑定切入单向绑定非常简单 就是把Model绑定到View 当我们用JavaScript代码更新Model时 View就会自动更新双向绑定就很容易联想到了 在单向绑定的基础上 用户更新了View Model的数
  • cocos cretor shader effect-the book of shader-4.二维矩阵

    2D Matrices 二维矩阵 前面章节 TheBookofShader开始 Shaping functions 造型函数 Color 颜色 Shapes 形状 平移 之前的章节我们学习了如何制作一些图形 而如何移动它们的技巧则是借助移动
  • 【设计模式】Chain of Responsibility 责任链式模式

    一 前言 责任链行为模式是行为模式的一种 行为模式涉及到算法和对象间职责的分配 行为模式不仅描述对象或类的模式 还描述它们之间的通信模式 行为模式分为 Template Method 模板方法 和 Interpreter 解析器行为模式 模
  • linux下安装mysql(rpm)方式安装

    前言 在linux中使用rpm安装包安装5以上版本的mysql的都可以参考这个 1 首先下载rpm安装包 要下载两个安装包一个client 一个server 有个镜像做的不错 下载地址mirrors sohu com mysql 进入后找到
  • 虚拟机centos7搭建k8s

    虚拟机centos7搭建k8s 1 踩坑大全 centos7安装的docker后 默认非root用户无法使用 所以需要创建docker组 把当前普通用户加入到组中 这里参考链接 设置docker非root用户正常使用 在给docker配置镜
  • Error creating bean with name ‘sqlSessionFactory‘ 、MySQL启动报错

    今天学习SpringSecurity的时候 选用了springboot 因为公司用的不是boot 所以 boot一直不是很熟悉 在此连接数据库的时候 遇到了一个bug Error creating bean with name sqlSes
  • UR机器人:位姿表示以及相关移动

    博主最近在做强化相关的任务 用到了UR5机械臂 所以本文主要讲述在使用过程中 对于UR机器人位姿的理解 在阅读本文之前 希望大家能够花一点时间读一下我的另一篇博文空间信息与坐标变换 本文如有错误的地方 欢迎大家指正 欢迎讨论 机座和工具 首
  • 麦科捷联合 Mellanox 加速eXtremeDB 集群性能

    2016年7月20日McObject 作为分布式数据库管理系统eXtremeDB 中集群功能的开发者 联合端对端以太网和无限宽带互联方案和服务领先供应商的Mellanox 共同宣布一个基准测试结果 该测试通过集成Mellanox的信息加速器
  • Node-RED配置

    配置文件 可通过配置文件配置Node RED 配置文件在哪 Node RED启动时 会在Node RED用户目录下寻找setting js文件 node red Windows中为系统盘 Users 当前用户 node red 若找不到 将
  • Vue3下pinia的状态管理原理和具体使用示例

    一 Pinia是什么 Pinia在Composition API的设计背景下 以Vuex下一代的构想设计了新的Vue存储状态管理库 Pinia 是一个基于 Vue 3 的状态管理库 它提供了一个可组合的 类型安全的 API 来管理 Vue
  • SpringMVC学习指南(2)

    文章目录 系列文章目录 前言 一 RequestMapping注解 1 1 value属性 1 2 method属性 1 3 params属性 1 4 header属性 1 5 通配符 二 PathVariable 注解 三 REST风格的
  • 安装64位SoildWorks时总是出现无法确定当前的订阅失效日期

    总共会出现两个弹窗信息 弹窗1 安装管理程序无法确定当前的的订阅失效日期 您想重新激活您的许可以更新信息吗 这个弹窗要点击 否 弹窗2 无法决定订阅服务失效日期 您必须使用 这个点击 确定 转载于 https www cnblogs com
  • matlab画对数坐标!

    在很多工程问题中 通过对数据进行对数转换可以更清晰地看出数据的某些特征 在对数坐标系中描绘数据点的曲线 可以直接地表现对数转换 对数转换有双对数坐标转换和单轴对数坐标转换两种 用loglog函数可以实现双对数坐标转换 用semilogx和s
  • 专访《白话区块链》作者蒋勇:学习区块链空谈不如实践

    上周HiBlock区块链社区联合蒋勇老师推出课程 区块链技术概念及智能合约实践 课程上线一天内报名42人 3天时间报名80多人 其中70人通过审核 超额完成第一期招生 为保证学员学习效果 不得已提前关闭报名通道 近几天来 很多学员还在留言问
  • 用C++实现数组切片

    这里写自定义目录标题 用C 实现数组切片 写的一般 权当抛砖引玉了 int slice int arr const int n int a new int n for
  • ubuntu20.4编译AOSP安卓源码(AndroidP android-9.0.0_r9)

    目录 代码下载 安装初始化依赖工具 配置repo工具 配置git信息 初始化仓库 配置编译环境 安装jdk 安装编译依赖 编译 初始化编译环境 选择编译目标 编译源码 启动模拟器 windows和Linux协同工作 遇到的问题解决 安装依赖
  • /etc/sysctl.conf 调优 & 优化Linux内核参数

    from http apps hi baidu com share detail 15652067 http keyknight blog 163 com blog static 3663784020104152407759 http bl
  • vue + video.js 加载多种视频流(HLS、FLV、RTMP、RTSP)

    起因 由于需要在一个项目内接入多种常用的视频流 所以接触到video js 这里就做个记录 框架 vue2 video js videojs contrib hls videojs flvjs es6 videojs flash video
  • 微信小程序支付 java

    话不多说 直接开撸 支付流程步骤 1 首先调用wx login方法获取code 通过code获取openid 2 java后台调用统一下单支付接口 这里会进行第一次签名 用来获取prepay id 3 java后台再次调用签名 这里会进行第
  • 锁升级过程和原理

    目录 同步方法与一般方法字节码对比 对象头中的锁信息 锁升级中涉及的四种锁 锁升级的过程 锁升级过程和原理 同步方法与一般方法字节码对比 public class SynchronizedTest1 public static void m