锁升级

2023-10-27

synchronized锁升级机制
普通对象对象头:
对象头
Mark Word与锁息息相关,后面的Klass Word与锁无关,不讨论。
Mark Word结构:
在这里插入图片描述

public class Syn {
	static int a=0;
	public static void main(String[] args)
	{
		Test t=new Test();
		Thread t1=new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				t.method1();
			}
			
		},"Thread1");
		t1.start();
		
		Thread t2=new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				t.method1();
			}
			
		},"Thread2");
		t2.start();
		
	}
}

class Test
{
	Object o=new Object();
	
	public void method1()
	{
		synchronized(o)
		{
			System.out.println("method1");
			method2();
		}
	}
	public void method2()
	{
     	synchronized(o)
		 {
		     System.out.println("method2");
		 }
	}
}



当锁对象创建好了

对象o默认开启偏向锁,开启的时候Mark Word格式如下:(找不到合适的图片,用64位说)
在这里插入图片描述
前54位非常重要,记录的是持有偏向锁的线程ID,但是刚刚创建的时候没有持有的线程,就是这样了:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000101
也就是说,没有线程占有这把锁,但他仍然等待有线程占有它。

当Thread1执行t.method1()

此时可以看到Mark Word为:
00000000 00000000 00000000 00000000 00011111 11101011 11010000 00000101
前54位是Thread1的ID,说明Thread1占有这个对象o,当代码执行到method2(),jvm会比较o的Mark Word的前54位和当前线程的ID,发现相等,正常执行。这个过程非常简单,在没有并发竞争情况下非常高效。

升级为轻量锁

当Thread2执行t.method2()的时候,分情况讨论。
如果这个时候Thread1已经执行完了(或者时间片到了进入等待状态),但是不会主动释放o的控制权。o中的线程ID仍然是Thread1的。这个时候Thread2会将o的线程ID置换为自己的线程ID,o仍然是偏向锁对象。
如果这个时候Thread1没有执行完成,则会发生争抢。这时候会将其升级为轻量级锁。
THread0指的是Thread1
轻量锁是自旋锁,即比较并赋值。
首先,Thread1将MarkWord赋值到栈帧的锁记录空间中,并将Object的标记替换为00,使用CAS赋值对象头。简单地说,比较后两位,如果后两位是01,说明没有其他线程动过这个对象,可以放心地赋值。如果后两位是00,说明这个锁对象已经被其他线程占有了。
请求轻量锁失败的线程会进入自旋状态,即循环等待。
如果是method2调用了
在这里插入图片描述
会加入一个栈帧
整个函数执行完了,还原到01.

锁膨胀

当自旋数量太多,或者自旋的线程太多,轻量锁会膨胀为重量锁。将自旋的线程阻塞。
为了避免无用的自旋,轻量级锁一旦膨胀为重量级锁就不会再降级为轻量级锁了;偏向锁升级为轻量级锁也不能再降级为偏向锁。

重量级锁

在这里插入图片描述

EntryList里面存放的是阻塞的线程,就是竞争锁对象失败的线程。
waitSet里面存放的是等待线程,就是已经取得了锁控制权以后(这一点非常非常重要!),调用wait()后的等待线程。如果没有得到锁控制权就wait,会报错。由其他线程调用了这个锁对象的notify()方法,会随机将WaitSet中的一个线程唤醒,加入Blocked中。所以唤醒以后这个线程未必立刻执行,也要参与锁竞争。notifyAll方法是将WaitSet中的所有线程唤醒,加入Blocked队列。
另外注意:调用notify/notifyAll方法的线程必须获得了锁对象的控制权,否则会报错!

public class Waitandif {
	public static void main(String[] args) {
		Object o=new Object();
		new Thread(new Runnable() {
			@Override
			public void run() {
				synchronized(o)
				{
					System.out.println("我是一号线程");	
					try {
						o.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("一号线程执行完了");
				}
			}
			}).start();
		
		new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				synchronized(o)
				{
					System.out.println("我是二号线程");
					try {
						o.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("二号线程执行完了");

				}
			}
			
		}).start();
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		synchronized(o)
		{
			o.notifyAll();  //获得了锁对象的控制权
		}

	}

}

我是一号线程
我是二号线程
二号线程执行完了
一号线程执行完了

wait和sleep的区别

(1)wait是对象方法,任何对象都可以调用;
sleep是Thread方法,是静态方法,只有Thread类可以用。
(2)wait会释放对象锁,sleep不会
(3)wait必须配合synchronized一起使用
(4)wait后,必须有其它线程执行唤醒方法,才能让睡眠线程运行。

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

锁升级 的相关文章

  • springboot项目打包的可执行jar运行报错

    文章目录 问题展现 问题解决 原理说明 加了spring boot maven plugin插件生成的MANIFEST MF文件 没加spring boot maven plugin插件生成的MANIFEST MF文件 问题展现 现在使用s
  • 《windows核心编程系列》二十一谈谈基址重定位和模块绑定

    http blog csdn net ithzhang article details 7058576
  • Aanconda 启动jupyter失败?Anaconda启动一闪一闪?

    Aanconda 启动jupyter失败 Anaconda启动一闪一闪 看不爽 首先 启动一闪一闪本身就这鸟样 不要担心出现这个问题 它就这个样子 不信 在cmd里面执行启动anaconda 程序 就不会一闪一闪了 自己去搜索怎么cmd 启
  • mysql四舍五入函数取两位小数_MySQL四舍五入函数ROUND(x)、ROUND(x,y)和TRUNCATE(x,y)

    MySQL四舍五入函数ROUND x ROUND x 函数返回最接近于参数x的整数 对x值进行四舍五入 实例 使用ROUND x 函数对操作数进行四舍五入操作 SQL语句如下 mysql gt SELECT ROUND 2 34 ROUND
  • 数据提取之JSON与JsonPATH

    JSON JavaScript Object Notation 是一种轻量级的数据交换格式 它使得人们很容易的进行阅读和编写 同时也方便了机器进行解析和生成 适用于进行数据交互的场景 比如网站前台与后台之间的数据交互 JSON和XML的比较
  • Andriodjie——欢迎页3秒跳转到主页+banner图片轮播

    Welocomepublic class Welocome extends Activity private final long SPLASH LENGTH 3000 Handler handler new Handler Overrid
  • 在设计BUCK分立电路中,电感该如何选择,需要注意哪些地方

    在Buck电路中 电感器是用于实现降压的核心元器件之一 通常情况下 选择合适的电感值可以提高电路的效率和稳定性 避免输出电压不稳定或者出现脉冲干扰等问题 选择电感大小需要考虑以下几个因素 输出电压和电流 电感值会影响到输出电压和电流的稳定性
  • Python程序设计选择题

    1 关于 Python 程序格式框架的描述 以下选项中错误的是 A Python语言的缩进可以采用Tab键实现 B Python单层缩进代码属于之前最邻近的一行非缩进代码 多层缩进代码根据缩进关 系决定所属范围 C 判断 循环 函数等语法形
  • android-apt plugin is incompatible with the Android Gradle plugin. Please use 'annotationProcessor'

    android apt plugin is incompatible with the Android Gradle plugin Please use annotationProcessor 分三步走 1 progect中类似于 clas
  • Mybatis查询 字段类型转换错误

    问题描述 Cannot convert string aaa to java sql Timestamp value nested exception is java sql SQLDataException Cannot convert
  • gauge自动化框架踩坑(六):关于csv

    一 语法 关于csv文件 官方文档只给出了语法 并没有举出实际的例子来说明 如何使用 语法
  • Error creating bean with name ‘userService‘: Unsatisfied dependency expressed through field‘userMap‘

    今天在做项目时遇到了idea报 Could not autowire No beans of UserMapper type found 的错误 记录以下解决过程 我的mapper注解使用的是 Mapper 在使用 Autowrited注解
  • Java校招面试经验汇总,看完直接跪服

    美团技术一面20分钟 晚7点 因为想到下周一才面试 我刚准备出去打个羽毛球 北京的电话就来了 面试官各种抱歉 说开会拖延了 1 自我介绍 说了很多遍了 很流畅捡重点介绍完 2 问我数据结构算法好不好 挺好的 其实心还是有点虚 不过最近刷了很
  • Android 录音功能无法正常使用

    具体现象 最近在做一个APP需要安装在智能手表上 有一个录音的功能 将开发的apk安装在手机和pad上面都能正常使用 录音文件也可以正常播放 但是安装到手表后 启动录音功能几秒钟录音文件就达几百兆 且录音文件不能够正常播放 通过调试信息也看
  • Python学习笔记(十九)————json相关

    目录 1 什么是json 2 json有什么用 3 json格式数据转化 4 Python数据和Json数据的相互转化 1 什么是json JSON 是一种轻量级的数据交互格式 可以按照 JSON 指定的格式去组织和封装数据 JSON 本质
  • Grafana 系列-统一展示-2-Prometheus 数据源

    系列文章 Grafana 系列文章 Grafana Prometheus 数据源 Grafana 提供了对 Prometheus 的内置支持 本文会介绍 Grafana Prometheus 也包括 Prometheus 的兼容实现 如 T
  • js保留有效数字

    JavaScript中数字保留有效数字位数的方法有三种 toFixed toExponential toPrecision 这三种方法都会把数字转成字符串 1 toFixed 根据小数点后的指定位数将数字转为字符串 不会使用指数计数法 2
  • 使用Vue手动封装树形控件组件

    提示 如果当下认为一件事很难做 那么不用犹豫直接做就OK 巨大的提升往往出现在反复的挣扎过后 跳出舒适圈 不断挑战自我 毕竟还年轻 因为已经完成了 索性就用上帝视角一次性把需要注意的东西都列出来 不怎么会循序渐进 原谅俺 1 需求整理 如上
  • 什么是过拟合和欠拟合

    今天突然被以前同学人问到什么是机器学习中的 过拟合 过拟合就是训练的时候效果很好损失函数值可以降得很低 但是到测试数据集的时候表现就不那么好了 就是过分依赖于现有训练数据集的特征造成的 可以加大数据集来进行训练 比如在图像领域可以通过拉伸旋
  • Fabric核心模块

    Fabric由五个核心模块组成的程序组 1 peer 主节点模块 负责存储区块链数据 运行维护链码 2 orderer 交易打包 排序模块 3 cryptogen 组织和证书生成模块 4 configtxgen 区块和交易生成模块 生成创始

随机推荐

  • Linux Clock

    http www wowotech net pm subsystem clk overview html Linux common clock framework 1 概述 http www wowotech net pm subsyste
  • 500 Request processing failed; nested exception is java.lang.NullPointerException

    类型 异常报告 消息 Request processing failed nested exception is java lang NullPointerException 描述 服务器遇到一个意外的情况 阻止它完成请求 报错原因 这种报
  • TensorFlow2 Fashion-MNIST图像分类(二)

    1 图像分类数据的标准化 本篇内容是 TensorFlow2 Fashion MNIST图像分类 一 的第二部分 请先阅读第一部分中的内容 上一部分内容最后提到 模型训练结果出现不拟合现象 主要原因就在于特征数据没有进行标准化处理 因此本部
  • Unity3d Animation动画详解。。。

    动画脚本 Animation Scripting Unity s 动画系统允许你创建一个漂亮的动画蒙皮角色 动画系统支持动画融合 混合 添加动画 步调周期时间同步 动画层 控制动画回放的所有方面 时间 速度 混合权重 每个顶点有1 2 4个
  • 机器学习之下游任务

    下游任务是该领域称为那些利用预训练模型或组件的监督学习任务
  • EtherCat--主站开源的C语言库SOEM-环境搭建

    一 SOEM主站环境搭建 一 安装VS 二 下载SOEM 1 3 1 源代码 链接地址 http openethercatsociety github io 三 安装WinPcap 4 1 3 exe 链接地址 https www winp
  • 3DsMAX一渲染就卡解决方法

    目前比较常见的3DMAX卡死原因有三个 一是win10输入法不兼容 二是内存和CPU运行过载 三是场景模型问题 1 兼容问题 win10的微软拼音不兼容 常见但很难让人相信的问题 C4D渲染卡死也可以这样解决 解决方法 打开 windows
  • 二维坐标系的转换

    二维坐标系的变换分为旋转变换和平移变换 一 旋转变换 假设已知基坐标系XOY中的一点P x y 坐标原点为O 绕点O旋转 可以求得点P在新坐标系X OY 中坐标值 x y 如下图所示 求解x 和y 的关键是坚持用已知的边做斜边来求解 结合上
  • 华为OD机试 - 求字符串中所有整数的最小和(Java)

    题目描述 输入字符串s 输出s中包含所有整数的最小和 说明 字符串s 只包含 a z A Z 合法的整数包括 1 正整数 一个或者多个0 9组成 如 0 2 3 002 102 2 负整数 负号 开头 数字部分由一个或者多个0 9组成 如
  • power相关:(一)低功耗设计目的与功耗的类型

    一 低功耗设计的目的 1 便携性设备等需求 电子产品在我们生活中扮演了极其重要的作用 便携性的电子设备便是其中一种 便携性设备需要电池供电 需要消耗电池的能量 在同等电能提供下 低功耗设计的产品就能够工作更长的时间 时间的就是生命 因此低功
  • 【MySQL】使用Visio绘制数据库关系模型图

    使用Visio绘制数据库关系模型图 1 新建项目 文件 新建 软件和数据库 数据库模型图 点击后 出现如下界面 2 绘制 左侧 实体关系 中将 实体 形状拖放到绘制界面 如下图 3 编辑实体名称 如下图 4 编辑列 点击 列 如下图 完成实
  • 【因果推断与机器学习】Causal_inference: Chapter 4

    Chapter4 Estimation 一旦我们找到了识别因果量的策略 我们就需要选择如何使用统计方法估计这些因果量 我们使用受实际计算应用程序启发的示例来描述最常用的方法 首先 我们介绍因果估计的基础知识 如何从已确定的估计值到估计器 我
  • Oracle入门使用

    表空间的创建 普通用户授权 sys登录 grant create tablespace to 用户名 grant drop tablespace to 用户名 给user01 一个临时用户的角色 grant connect to user0
  • make -j时不知道cpu核数设置多大合适

    make j nproc nproc 就是你可以设置的当前机器的最大值了
  • Python使用Psycopg2访问PostgreSQL

    本文将关注 安装Psycopg2并使用其API访问PostgreSQL数据库 然后带您完成数据插入 数据检索 数据更新和数据删除 接下来 它将介绍事务管理 连接池和错误处理技术 以使用PostgreSQL开发健壮的python程序 使用pi
  • Vue性能优化

    Vue 项目性能优化 现在Vue3 0都快发布了为什么还要优化2 0的项目 因为市场上公司90 的项目全是Vue2 0的项目 迁移的话成本太高 所以只能进行性能的优化调整 废话就不多赘述了 直接开始吧 一 活用异步组件 Vue cli打包的
  • CXL 2.0 Device配置空间寄存器组成

    目录 1 配置空间 1 1 PCI Power Management Capability Structure 1 2 PCI Express Capability Structure 2 扩展配置空间 2 1 Virtual Channe
  • Java~实现简单的扑克牌,洗牌,发牌,玩捉鬼游戏(讲解详细,代码齐全)

    目录 一 扑克牌的定义 1 牌的定义 2 玩家的定义 二 扑克牌的操作 初始化 洗牌 发牌等 1 初始化 2 洗牌 3 发牌 三 初始化 洗牌 发牌代码 全 四 捉鬼游戏 首先一副扑克牌是54张 这里我们去掉大小王 也就是52张扑克牌 有
  • layui多文件上传_EasyUI的filebox组件实现多文件上传的步骤

    EasyUI的filebox组件实现多文件上传的步骤 新增回款记录详情里面有个添加回款记录文件的按钮 点击选择文件 文件既可以选择一个也可以选择多个 img 点击并拖拽以移动
  • 锁升级

    synchronized锁升级机制 普通对象对象头 Mark Word与锁息息相关 后面的Klass Word与锁无关 不讨论 Mark Word结构 public class Syn static int a 0 public stati