当前位置:首页 > 科技  > 软件

不吃饭也要掌握的Synchronized锁升级过程

来源: 责编: 时间:2023-11-08 09:10:54 453观看
导读一、前言在面试题中经常会有这么一道面试题,谈一下synchronized锁升级过程?之前背了一些,很多文章也说了,到底怎么什么条件才会触发升级,一直不太明白。实践是检验真理的唯一标准,今天就和大家一起实践一下,什么条件才会升级

8CX28资讯网——每日最新资讯28at.com

一、前言

在面试题中经常会有这么一道面试题,谈一下synchronized锁升级过程?8CX28资讯网——每日最新资讯28at.com

之前背了一些,很多文章也说了,到底怎么什么条件才会触发升级,一直不太明白。8CX28资讯网——每日最新资讯28at.com

实践是检验真理的唯一标准,今天就和大家一起实践一下,什么条件才会升级!8CX28资讯网——每日最新资讯28at.com

二、为什么会有锁升级过程?

在实践之前,我们先一步步的来了解!为什么要升级呢?8CX28资讯网——每日最新资讯28at.com

在JDK1.6之前,synchronized的性能一直没有ReentrantLock性能高,主要是因为synchronized涉及到用户态和内核态的切换,这个是在操作系统和硬件是非常消耗资源的。8CX28资讯网——每日最新资讯28at.com

经过不断的统计分析,发现大部分时间一个锁都是一个线程去获取,如果只有一个线程来尝试加锁,就是重量级锁,显而浪费资源。8CX28资讯网——每日最新资讯28at.com

「总之,锁的升级过程是为了提高多线程环境下的性能和吞吐量,减少同步操作的开销,并尽量避免线程切换的开销。Java虚拟机根据线程竞争的情况和锁的使用情况自动进行锁的升级和降级,以优化多线程程序的性能。」8CX28资讯网——每日最新资讯28at.com

此时,就引入了很多锁类型,下面我们来具体看看!8CX28资讯网——每日最新资讯28at.com

三、锁分类

偏向锁:偏向锁是为了解决单线程访问的场景,偏向锁允许第一个访问共享资源的线程获得锁,把线程id存到对象头中,后续的访问可以直接获得锁,而不需要竞争。8CX28资讯网——每日最新资讯28at.com

轻量级锁:当一个或多个线程尝试获取同一个锁时,偏向锁会升级为轻量级锁。轻量级锁采用CAS(Compare and Swap)操作来减小锁的竞争。采用自适应自旋!8CX28资讯网——每日最新资讯28at.com

重量级锁:操作系统的调度器会介入,将竞争锁的线程挂起,直到锁被释放为止,重量级锁的开销相对较高。8CX28资讯网——每日最新资讯28at.com

「补充:」8CX28资讯网——每日最新资讯28at.com

「自适应自旋的基本思想是根据锁的争用情况,决定线程是否应该自旋等待,以及自旋等待的时间,一般情况为自旋10次。」8CX28资讯网——每日最新资讯28at.com

四、对象内存结构

我们在说锁的升级过程之前,需要了解一下对象的内存结构,因为在锁升级过程中会往对象头上进行填充信息!一个对象分为:对象头、实例数据、对其填充位三部分组成。8CX28资讯网——每日最新资讯28at.com

8CX28资讯网——每日最新资讯28at.com

我们本次主要用到对象头,我们再看一下详细的对象头信息里有什么:8CX28资讯网——每日最新资讯28at.com

8CX28资讯网——每日最新资讯28at.com

四、图解锁升级过程

先来一个简图:8CX28资讯网——每日最新资讯28at.com

8CX28资讯网——每日最新资讯28at.com

下面引用百度上的一张详细一点的图:8CX28资讯网——每日最新资讯28at.com

8CX28资讯网——每日最新资讯28at.com

我们来详细的说一下锁的升级过程,在每一个锁切换时的条件是什么?8CX28资讯网——每日最新资讯28at.com

在JDK8时,偏向锁默认是在程序启动后4s自动开启的,在JKD15之后默认是不开启的!8CX28资讯网——每日最新资讯28at.com

可以设置无延迟时间启动:-XX:BiasedLockingStartupDelay=0也可以不启动偏向锁:-XX:-UseBiasedLocking = false。8CX28资讯网——每日最新资讯28at.com

直接说有点不形象,我们下面结合代码来实战,看一下具体情况!8CX28资讯网——每日最新资讯28at.com

五、实战锁升级过程

为了我们能够查询对象结构,我们需要引入jar帮助我们查看!8CX28资讯网——每日最新资讯28at.com

1、导入依赖

「注意」:不要使用高版本的,高版本不显示2进制,不好观察!8CX28资讯网——每日最新资讯28at.com

<dependency>    <groupId>org.openjdk.jol</groupId>    <artifactId>jol-core</artifactId>    <version>0.10</version></dependency>

2、实战代码和解析

我们来从序号1开始,上面也说了默认4s后开启偏向锁,我们会发现序号1打印的对象头序号为:001我们的对象大小为20,内部帮我们补位来满足是8的倍数。方便操作系统进行寻址,不会有碎片组合!这个大家可以详细搜一下,这里就一带而过了哈!8CX28资讯网——每日最新资讯28at.com

8CX28资讯网——每日最新资讯28at.com

此时我们睡眠6s,包装偏向锁开启成功!8CX28资讯网——每日最新资讯28at.com

我们来到序号2,开启了偏向锁,我们发现对象头序号为:101。8CX28资讯网——每日最新资讯28at.com

「节点:从无锁到偏向锁切换的条件:JDK8中默认4s后开启,JDK15需要手动开启」。8CX28资讯网——每日最新资讯28at.com

8CX28资讯网——每日最新资讯28at.com

来到序号3和4一起说吧,当我们进行synchronized加锁时,对象的头信息中会记录上当前线程的id,下面再有加锁的,直接判断线程id是否一致,一致直接进入代码块。不一致后面再说!我们发现在序号4时,已经出了代码块,在此查询加锁的对象,信息依旧在,不会进行移除,这就是偏向,直到下一个线程把上一个替换掉!8CX28资讯网——每日最新资讯28at.com

代码里循环了三次,对象都是一样的!8CX28资讯网——每日最新资讯28at.com

「节点:在只有一个线程访问代码块的时候,对象中会记录当前线程id。」8CX28资讯网——每日最新资讯28at.com

8CX28资讯网——每日最新资讯28at.com

「以上都是在一个线程来访问的情况下」8CX28资讯网——每日最新资讯28at.com

来到序号5,我们新建了一个线程来进行加锁。此时会判断当前线程id和新线程id是否一致,不一致就会认为有竞争关系,会立刻切换为轻量级锁。对象头序号为:008CX28资讯网——每日最新资讯28at.com

「节点:当有两个线程交替获取锁时,不存在同时竞争获取锁时。」8CX28资讯网——每日最新资讯28at.com

8CX28资讯网——每日最新资讯28at.com

序号6和7一起说,我们让上面序号5这个线程获取锁后睡眠3s,持续获得锁。在开启一个新的线程去竞争获取锁,此时先进行自适应CAS自旋,一般10次后一直没办法获取锁,判定为激烈竞争关系。变为重量级锁,序号7线程会进行放到阻塞队列中。对象头序号为:10。8CX28资讯网——每日最新资讯28at.com

经过睡眠后,序号6在此获取对象的信息时,已经变为重量级锁!8CX28资讯网——每日最新资讯28at.com

「节点:有两个及其以上线程同时获取锁,且在自适应自旋范围内没有获取到锁」。8CX28资讯网——每日最新资讯28at.com

8CX28资讯网——每日最新资讯28at.com

下面是代码,大家可以在本地试一下!8CX28资讯网——每日最新资讯28at.com

/** * jvm默认延时4s自动开启偏向锁, * 可通过 -XX:BiasedLockingStartupDelay=0 * 取消延时如果不要偏向锁,可通过-XX:-UseBiasedLocking = false * @author wangzhenjun * @date 2023/10/18 14:42 */public class LockUp {    @SneakyThrows    public static void main(String[] args) {        LockInfo lockInfo = new LockInfo();        System.out.println("1.无状态:" + ClassLayout.parseInstance(lockInfo).toPrintable());        Thread.sleep(6000);        LockInfo lock = new LockInfo();        System.out.println("2.已经开启了偏向锁模式:" + ClassLayout.parseInstance(lock).toPrintable());        for (int i = 0; i < 3; i++) {            synchronized (lock) {                System.out.println("3.偏向锁模式下,加锁状态:" + ClassLayout.parseInstance(lock).toPrintable());            }            System.out.println("4.锁释放了,加锁状态:" + ClassLayout.parseInstance(lock).toPrintable());        }        new Thread(() -> {            synchronized (lock) {                System.out.println("5.轻量级锁,加锁状态:" + ClassLayout.parseInstance(lock).toPrintable());                System.out.println("睡眠3s");                try {                    Thread.sleep(3000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println("6.轻量级锁=>重量级锁,加锁状态:" + ClassLayout.parseInstance(lock).toPrintable());            }        }).start();        Thread.sleep(1000);        new Thread(() -> {            synchronized (lock) {                System.out.println("重量级锁,加锁状态:" + ClassLayout.parseInstance(lock).toPrintable());            }        }).start();    }}

六、总结与拓展

经过实战,我们知道了每一个的切换条件,可以在面试中好好地回答了。不至于面试官反问一下就不坚定了!8CX28资讯网——每日最新资讯28at.com

关于切换到重量级锁后,有兴趣的话,可以下载openJDK源码去看一下关于hotspot/src/share/vm/runtime/objectMonitor.cpp和hotspot/src/share/vm/runtime/objectMonitor.hpp。8CX28资讯网——每日最新资讯28at.com

源码下载地址:https://github.com/openjdk/jdk88CX28资讯网——每日最新资讯28at.com

objectMonitor.cpp:是 OpenJDK 中实现 Java 同步机制的核心部分,它负责管理对象监视器,确保多线程程序能够正确协同工作,实现线程同步和等待/通知机制。8CX28资讯网——每日最新资讯28at.com

8CX28资讯网——每日最新资讯28at.com

objectMonitor.hpp:主要用于定义对象监视器的接口和数据结构,为实际的对象监视器的实现提供了基础。8CX28资讯网——每日最新资讯28at.com

8CX28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-17661-0.html不吃饭也要掌握的Synchronized锁升级过程

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 一文读懂Android架构演进历程

下一篇: 一文带你了解Spring Actuator

标签:
  • 热门焦点
  • 鸿蒙OS 4.0公测机型公布:甚至连nova6都支持

    华为全新的HarmonyOS 4.0操作系统将于今天下午正式登场,官方在发布会之前也已经正式给出了可升级的机型产品,这意味着这些机型会率先支持升级享用。这次的HarmonyOS 4.0支持
  • 深度探索 Elasticsearch 8.X:function_score 参数解读与实战案例分析

    在 Elasticsearch 中,function_score 可以让我们在查询的同时对搜索结果进行自定义评分。function_score 提供了一系列的参数和函数让我们可以根据需求灵活地进行设置。近期
  • 三万字盘点 Spring 九大核心基础功能

    大家好,我是三友~~今天来跟大家聊一聊Spring的9大核心基础功能。话不多说,先上目录:图片友情提示,本文过长,建议收藏,嘿嘿嘿!一、资源管理资源管理是Spring的一个核心的基础功能,不
  • 一文搞定Java NIO,以及各种奇葩流

    大家好,我是哪吒。很多朋友问我,如何才能学好IO流,对各种流的概念,云里雾里的,不求甚解。用到的时候,现百度,功能虽然实现了,但是为什么用这个?不知道。更别说效率问题了~下次再遇到,
  • 梁柱接棒两年,腾讯音乐闯出新路子

    文丨田静 出品丨牛刀财经(niudaocaijing)7月5日,企鹅FM发布官方公告称由于业务调整,将于9月6日正式停止运营,这意味着腾讯音乐长音频业务走向消亡。腾讯在长音频领域还在摸索。为
  • 2纳米决战2025

    集微网报道 从三强争霸到四雄逐鹿,2nm的厮杀声已然隐约传来。无论是老牌劲旅台积电、三星,还是誓言重回先进制程领先地位的英特尔,甚至初成立不久的新
  • 7月4日见!iQOO 11S官宣:“鸡血版”骁龙8 Gen2+200W快充加持

    上半年已接近尾声,截至目前各大品牌旗下的顶级旗舰都已悉数亮相,而下半年即将推出的顶级旗舰已经成为了数码圈爆料的主流,其中就包括全新的iQOO 11S系
  • 首发天玑9200+ iQOO Neo8系列发布首销售价2299元起

    2023年5月23日晚,iQOO Neo8系列正式发布。其中,Neo系列首款Pro之作——iQOO Neo8 Pro强悍登场,限时售价3099元起;价位段最强性能手机iQOO Neo8同期上市
  • onebot M24巧系列一体机采用轻薄机身设计,现已在各平台开售

    onebot M24 巧系列一体机目前已在线上线下各平台同步开售。onebot M24 巧系列采用一体化轻薄机身设计,最薄处为 10.15mm,拥有宝石红、午夜蓝、石墨绿、雅致
Top