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以传统的方式去竞争锁资源


一、无锁

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以传统的方式去竞争锁资源

相关推荐
摇滚侠36 分钟前
Java 全栈开发实战教程 课程笔记 34-36
java·笔记
芝士熊爱编程41 分钟前
创建型模式-单例模式
java·单例模式·设计模式
大模型码小白1 小时前
Spring AI 框架实战:Java 后端集成大模型的架构设计与工程落地
java·人工智能·python·spring
weixin_BYSJ19871 小时前
「课设设计」springboot校园超市助购系统26449 (附源码)
java·javascript·spring boot·python·django·flask·php
栋***t1 小时前
从“纸质试卷”到“AI智能组卷”,麦塔在线考试系统如何重构出题逻辑?
java·大数据·人工智能·算法·重构
CHANG_THE_WORLD1 小时前
深入理解递归:从函数调用到调用栈的完整执行过程
java·开发语言·算法
xexpertS1 小时前
CI/CD 熔断机制:如何通过编排级熔断器提升开发者效率
java·linux·运维
zy happy2 小时前
VMware虚拟机添加新的硬盘
java·linux·jvm·docker
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题 第192题】【08_Kafka篇】第8题:死信队列是什么?延时队列是什么?
java·kafka·消息队列·死信队列·延时队列
meng半颗糖3 小时前
3.Java流程控制语句
java·开发语言·intellij-idea