Java——》synchronized锁升级

推荐链接:
    总结——》【Java】
    总结——》【Mysql】
    总结——》【Redis】
    总结——》【Kafka】
    总结——》【Spring】
    总结——》【SpringBoot】
    总结——》【MyBatis、MyBatis-Plus】
    总结——》【Linux】
    总结——》【MongoDB】
    总结——》【Elasticsearch】

Java——》synchronized锁升级

synchronized在jdk1.6之前,一直是重量级锁,只要线程获取锁资源失败,直接挂起线程(用户态切换到内核态),效率低,所以JDK团队在Jdk1.6将synchronized做了3方面优化:锁升级、锁消除、锁膨胀。

锁就是对象,Java中所有对象都是锁。

描述
无锁/匿名偏向无锁:没有开启偏向锁偏向锁延迟开启时间内),没有线程拿锁
匿名偏向:开启偏向锁,没有线程拿锁,没有偏向任何线程
偏向锁只有一个线程来拿锁资源,没有竞争
轻量级锁偏向锁出现竞争时,会升级到轻量级锁(触发偏向锁撤销),以CAS的方式(自适应自旋锁)去竞争锁资源,不会让线程挂起。(LockRecord)
重量级锁直接采用MarkWord指向的ObjectMonitor以传统的方式去竞争锁资源

image.png
image.png

一、无锁

1、无锁

一般情况下,new出来的一个对象,是无锁状态
因为偏向锁有延迟,在启动JVM的4s中,不存在偏向锁

2、匿名偏向

如果关闭了偏向锁延迟的设置,new出来的对象,就是匿名偏向,但没有偏向任何线程。

java">//关闭延迟开启偏向锁
-XX:BiasedLockingStartupDelay=0
//4s之后开启偏向锁
-XX:BiasedLockingStartupDelay=4

//禁止偏向锁
-XX:-UseBiasedLocking 
//启用偏向锁
-XX:+UseBiasedLocking 

二、偏向锁

没有线程的竞争,只有一个线程在获取锁资源。

1、获取锁资源的过程(锁升级过程)

当某一个线程来获取这个锁资源时,发现没有线程占用锁资源,并且锁是偏向锁,使用CAS的方式,设置对象的线程ID为当前线程,获取到锁资源,下次当前线程再次获取锁资源时,只需要判断是偏向锁,并且对象的线程ID是当前线程ID就直接获得到锁资源。如果对象的线程ID不是当前线程ID,也就是说偏向锁状态出现了锁竞争的情况,就触发锁升级,升级为轻量级锁

2、为什么要有偏向锁延迟

JVM在启动时,需要加载大量的.class文件到内存中,这个操作会涉及到synchronized的使用,为了避免出现偏向锁撤销导致启动效率变慢,所以JVM启动时,有一个延迟4s开启偏向锁的操作。

偏向锁是延迟开启的,并且在开启偏向锁之后,默认不存在无锁状态,只存在匿名偏向。

3、为什么偏向锁撤销会导致启动变慢

偏向锁升级到轻量锁时,会触发偏向锁撤销
(1)偏向锁撤销需要等到一个安全点(STW),才可以做偏向锁撤销。
(2)偏向锁撤销的成本太高(消耗资源)

4、偏向锁撤销安全点

  • GC
  • 方法返回之前
  • 调用某个方法之后
  • 抛出异常的位置
  • 循环的末尾

5、偏向锁重入

用到了LockRecord,只不过内部不会存储hashcode信息等等,在偏向锁重入时,每次都会压栈一个LockRecord,从而实现偏向锁重入。

6、偏向锁会降级到无锁状态吗以及如何降

会。
偏向锁状态下,获取当前对象的hashcode值,会因为对象头空间无法存储hashcode,导致降级到无锁状态。

三、轻量级锁

如果出现了多个线程的竞争,就要升级为轻量级锁(有可能直接从无锁变为轻量级锁,也有可能从偏向锁升级为轻量级锁,会触发偏向锁撤销)。
轻量级锁的是基于CAS尝试获取锁资源,这里会用到自适应自旋锁,JVM会自动的根据上次CAS成功与否,决定这次自旋多少次。

  • 如果成功获取到,拿着锁资源走
  • 如果自旋了一定次数,没拿到锁资源,锁升级重量级锁

四、重量级锁

轻量级锁CAS一段次数后,没有拿到锁资源,升级为重量级锁。线程拿不到锁,就挂起。

java">public static void main(String[] args) throws InterruptedException {
    Thread.sleep(5000);
    Object o = new Object();
    System.out.println(ClassLayout.parseInstance(o).toPrintable());

    new Thread(() -> {

        synchronized (o){
            //t1  - 偏向锁
            System.out.println("t1:" + ClassLayout.parseInstance(o).toPrintable());
        }
    }).start();
    //main - 偏向锁 - 轻量级锁CAS - 重量级锁
    synchronized (o){
        System.out.println("main:" + ClassLayout.parseInstance(o).toPrintable());
    }
}

1、重量级锁会降级到偏向锁或者是轻量级锁

不会

2、如何竞争锁资源

直接采用MarkWord指向的ObjectMonitor以传统的方式去竞争锁资源


http://www.niftyadmin.cn/n/5019021.html

相关文章

【LeetCode-简单题】69. x 的平方根

文章目录 题目方法一:二分查找 题目 方法一:二分查找 假设求8的平方根,那就设置left 0 ,right 8; 每次取最中间的元素的平方和8对比,如果大于8,则right mid-1,如果小于8 left mi…

容器编排学习(九)服务管理与用户权限管理

一 service管理 1 概述 容器化带来的问题 自动调度:在 Pod 创建之前,用户无法预知 Pod 所在的节点,以及 Pod的IP 地址一个已经存在的 Pod 在运行过程中,如果出现故障,Pod也会在新的节点使用新的IP 进行部署应用程…

Python 操作 CSV

使用过 CSV 文件都知道:如果我们的电脑中装了 WPS 或 Microsoft Office 的话,.csv 文件默认是被 Excel 打开的,那么什么是 CSV 文件?CSV 文件与 Excel 文件有什么区别?如何通过 Python 来操作 CSV 文件呢?带…

jQuery选择器参考手册

选择器实例选取*$(“*”)所有元素#id$(“#lastname”)id“lastname” 的元素.class$(“.intro”)class“intro” 的所有元素.class,.class$(“.intro,.demo”)class 为 “intro” 或 “demo” 的所有元素element$(“p”)所有 <p> 元素el1,el2,el3$(“h1,div,p”)所有 <…

PYTHON 3.10中文版官方文档

大家好&#xff0c;我是涛哥。 很多问我涛哥学习Python看啥&#xff0c;一般我都会建议多看看官方文档&#xff0c;因为官方文档真的周到了&#xff0c;啥内容都有&#xff0c;比如新手安装&#xff0c;标准库&#xff0c; AIP参考手册&#xff0c;常见FAQ问题&#xff0c;太…

记录一次开机内存分析的全过程

作者&#xff1a;zzy的学习笔记 记录一次开机内存分析的全过程&#xff0c;尽量详尽的介绍常用内存分析工具和命令行的使用&#xff0c;结合具体问题探讨开机内存分析的实践经验。通过这篇文章我会介绍开机内存的常用测试分析工具的基本使用方法&#xff0c;以及如何通过抓取出…

N - 不重叠的线段

X轴上有N条线段,每条线段有1个起点S和终点E。最多能够选出多少条互不重叠的线段。(注&#xff1a;起点或终点重叠,不算重叠)。 例如&#xff1a;[1 5][2 3][3 6],可以选[2 3][3 6],这22条线段互不重叠。 投入 第1行&#xff1a;1个数N,线段的数量&#xff08;1<2≤N≤1000…

【码银送书第六期】《ChatGPT原理与实战:大型语言模型的算法、技术和私有化》

写在前面 2022年11月30日&#xff0c;ChatGPT模型问世后&#xff0c;立刻在全球范围内掀起了轩然大波。无论AI从业者还是非从业者&#xff0c;都在热议ChatGPT极具冲击力的交互体验和惊人的生成内容。这使得广大群众重新认识到人工智能的潜力和价值。对于AI从业者来说&#xf…