synchronized锁升级

ops/2024/9/23 18:32:47/

为什么会有锁升级:

原因就是具体问题具体分析,每一个锁状态来对应不同的情况状态,使之资源的开销最小,效率最高。

四种锁状态:

1.无锁

2.偏向锁

3.轻量级锁

4.重量级锁

状态描述:

无锁:即线程没有加锁,为无锁状态

偏向锁:只有单个线程加锁时,此时没有锁竞争

轻量级锁:一个或多个线程通过CAS的方式自选竞争锁资源,临界区运行时间较短的情况

重量级锁:多个线程争夺锁资源,临界区运行时间较长,此时会调用内核的锁资源,没有争抢到锁资源的线程直接放入阻塞队列,开销较大。


锁状态升级可视化:

使用maven项目,引用依赖

<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.9</version>
</dependency>

代码:
public class mySynUpdate {public static void main(String[] args) {mySynUpdate mySynUpdate = new mySynUpdate();System.out.println(ClassLayout.parseInstance(mySynUpdate).toPrintable());}
}


想要看懂这个输出结果,我们需要知道一些其他知识:

对象的组成对象头 + 实例部分 + 对齐部分

对象头:Mark Word + 类型指针

Mark Word示意图:

故Mark Word存储的就是该目标对象的锁状态信息,从图中我们可以看到,上面各个栏的bit位加起来刚好是64位,也就是8个字节,回到上面那幅图


无锁状态:


偏向锁状态:

public class mySynUpdate {static private Object loker = new Object();static class myTask implements Runnable{@Overridepublic void run() {synchronized (loker){String test="";for (int i = 0; i < 1000; i++) {test += "2";}System.out.println(ClassLayout.parseInstance(new myTask()).toPrintable());}}}public static void main(String[] args) throws InterruptedException {mySynUpdate m = new mySynUpdate();//对象由三部分组成:对象头 实例数据  对其填充//Object 对象头:Mark Word + 类型指针//Mark Word 占8个字节 --- 64位  记录锁状态//此时没有实例数据 所以前两行为Mark Word----8个字节   第三行为类型指针:被压缩了----4个字节  最后一行为对其填充:总大小必须是8的倍数//无锁时状态位:偏向锁0  锁状态位01  001//一个线程加锁时:转换成偏向锁  偏向锁1 锁状态位01  101myTask mt = new myTask();new Thread(mt).start();}
}

此时我们发现:咦,不是已经加锁了吗  状态码为啥还是001---无锁状态:

原来,偏向锁会延迟启动,默认是程序启动后4s,故我们可以让执行内容休眠4秒再看内部


static private Object loker = new Object();static class myTask implements Runnable{@Overridepublic void run() {synchronized (loker){String test="";for (int i = 0; i < 1000; i++) {test += "2";}try {Thread.sleep(4000);System.out.println(ClassLayout.parseInstance(new myTask()).toPrintable());} catch (InterruptedException e) {e.printStackTrace();}}}}

此时的锁状态就从001变成101了----->偏向锁


轻量级锁:---->重量级锁  qwq

   static Object loker = new Object();static class myTask implements Runnable{@Overridepublic void run() {synchronized (loker){String test="";for (int i = 0; i < 1000; i++) {test += "2";}}}}public static void main(String[] args) throws InterruptedException {myTask mt = new myTask();myTask mt1 = new myTask();System.out.println(ClassLayout.parseInstance(mt).toPrintable());Thread t1= new Thread(mt);t1.start();Thread t2 = new Thread(mt1);t2.start();t1.join();t2.join();System.out.println("**********轻量级锁*********");System.out.println(ClassLayout.parseInstance(loker).toPrintable());}

遗憾的是,结果并不像我们预期那样,锁状态位变成了10---->重量级锁,这里的话作者也不知道为啥,也就两个线程争夺锁资源哇,为啥就变成重量级锁了

欢迎大家补充说明~


http://www.ppmy.cn/ops/21230.html

相关文章

webpack-babel2

浏览器的兼容性问题 浏览器的兼容性问题不知包括随屏幕大小而变化&#xff0c;还包括针对浏览器支持的特性&#xff08;如css特性&#xff0c;js特性&#xff09; 做处理。 目前市场上有很多浏览器&#xff1a;Chrome,Safari,IE,Edge等&#xff0c;要根据它们的市场占有率来决…

【Java那些事】@TableField对字段的自动填充

问题&#xff1a;当你有个对象User时&#xff0c;这个User对象的属性还有类似createTime &#xff0c;updateTime的属性&#xff0c;每次创建这个对象都要设置createTime &#xff0c;updateTime&#xff0c;对这个对象User进行操作又要来更新它的updateTime&#xff0c;是不是…

逆数对(树状数组的方法)

本题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 题目&#xff1a; 样例&#xff1a; 输入 5 4 5 1 3 2 输出 7 思路&#xff1a; 根据题意&#xff0c;求逆序对总数。 逆序对含义&#xff1a;如果数组中的两个不同位置&#xff0c;前面的数字比后面的数字严格大&…

FebHost:顶级域名、通用域名、国别域名注册介绍

在创建网站时&#xff0c;选择适当的顶级域名是至关重要的。顶级域名不仅有助于传播产品信息&#xff0c;还能提高受众的信任度和参与度&#xff0c;进而改善品牌记忆。 顶级域名有各种类型&#xff0c;每种都有其特定用途。最常见的两种顶级域是通用顶级域&#xff08;gTLD&a…

设计模式- 模板方法模式(Template Method Pattern) 结构|原理|优缺点|场景|示例

设计模式&#xff08;分类&#xff09; 设计模式&#xff08;六大原则&#xff09; 创建型&#xff08;5种&#xff09; 工厂方法 抽象工厂模式 单例模式 建造者模式 原型模式 结构型&#xff08;7种&#xff09; 适配器…

微信小程序详解

微信小程序是一种无需下载安装即可使用的应用&#xff0c;它实现了应用“触手可及”的梦想&#xff0c;用户只需扫一扫或搜索一下即可打开应用。微信小程序全面开放申请后&#xff0c;企业、政府、媒体、其他组织或个人开发者均可申请注册。 微信小程序的特点包括&#xff1a;…

Selenium web自动化测试环境搭建

Selenium web自动化环境搭建主要要经历以下几个步骤&#xff1a; 1、安装python 在python官网&#xff1a;Welcome to Python.org&#xff0c;根据各自对应平台如&#xff1a;windows&#xff0c;下载相应的python版本。 ​ 下载成功后&#xff0c;点击安装包&#xff0c;一直…

socket编程-----常用socket编程函数

操作系统&#xff1a;Linux 编程语言&#xff1a;C语言 简述&#xff1a;socket编程函数是socket编程中的基础&#xff0c;通过组合使用它们&#xff0c;可以实现各种网络通信功能。 socket编程函数较多&#xff0c;在这里只是列出较为常用的socket函数 socket()函数 socket()函…