java八股文面试[多线程]——synchronized锁升级过程

速记:偏向-轻量-重量

锁膨胀

上面讲到锁有四种状态,并且会因实际情况进行膨胀升级,其膨胀方向是:无锁------>偏向锁------>轻量级锁------>重量级锁 ,并且膨胀方向不可逆

一.锁升级理论.

在synchronized锁升级过程中涉及到以下几种锁.先说一下这几种锁是什么意思.

偏向锁:只有一个线程 争抢锁资源的时候.将线程拥有者标识为当前线程.

轻量级锁(自旋锁):一个或多个线程 通过CAS去争抢锁,如果抢不到则一直自旋.

重量级锁:多个线程争抢锁,向内核申请锁资源,将未争抢成功的锁放到队列中直接阻塞.

为什么要有锁的升级过程 ?

在最开始的时候,其实就是无锁直接到重量级锁,但是重量级锁需要向内核申请额外的锁资源 ,这就涉及到用户态和内核态的转换,比较浪费资源,而且大多数情况下,其实还是一个线程去争抢锁,完全不需要重量级锁.

锁的具体升级过程(通常情况下):

1.当只有一个线程去争抢锁的时候,会先使用偏向锁,就是给一个标识,说明现在这个锁被线程a占有.

2.后来又来了线程b,线程c,说凭什么你占有锁,需要公平的竞争,于是将标识去掉,也就是撤销偏向锁

3.升级为轻量级锁,三个线程通过CAS进行锁的争抢(其实这个抢锁过程还是偏向于原来的持有偏向锁的线程).现在线程a占有了锁,线程b,线程c一直在循环尝试获取锁,后来又来了十个线程,一直在自旋,那这样等着也是干耗费CPU资源 ,所以就将锁升级为重量级锁,向内核申请资源,直接将等待的线程进行阻塞.

锁升级的过程如下所示:

什么情况下偏向锁才会升级为轻量级锁,什么时候轻量级锁才会升级为重量级锁?

只有一个线程的时候就是偏向锁(当偏向锁开启的时候,偏向锁默认开启),当争抢的线程超过一个 ,升级为轻量级锁.

当自旋的线程循环超过10次 ,或者线程等待的数量超过cpu的1/2 ,升级为重量级锁.其实轻量级锁就适用于那种执行任务很短的线程,可能通过一两次自旋,就能够获取到锁.

开启偏向锁一定比轻量级锁高效吗?

不一定,比如在一开始已经知道某个资源就需要被多个线程争抢,此时就不需要开启偏向锁,因为偏向锁给了标识之后,还需要取消这个标识 ,重新抢锁,比如在JVM中,偏向锁默认是延迟4秒 才开始的,因为JVM在启动的时候需要多个线程竞争资源,并且这个都是一开始知道的.

对象在内存中的内存布局

在堆中,一个对象会包含以下四个部分:

我们如果使用synchronized对某个对象进行加锁,就会体现在mark word区域.最低两个字节 加以标识.

如下如所示:

重量级锁 对应 10

轻量级锁 对应 00
无锁和偏向锁都对应01 ,这个时候需要倒数第三个字节 加以区分,

即 无锁 对应 001, 偏向锁 对应 101

其他注意点:

并不是一定会 有一个偏向锁->轻量级锁->重量级锁的过程,比如如果出现严重的耗时操作(sleep,或者wait等),就会直接由偏向锁升级为重量级锁.

TODO

知识来源:

【并发与线程】Sychronized的偏向锁、轻量级锁、重量级锁_哔哩哔哩_bilibili

【2023年多线程面试】无锁、偏向锁、轻量级锁、重量级锁升级过程(多线程面试)_哔哩哔哩_bilibili

synchronized锁升级过程_程序员bling的博客-CSDN博客

相关推荐
一只叫煤球的猫5 小时前
写代码很6,面试秒变菜鸟?不卖课,面试官视角走心探讨
前端·后端·面试
皮皮林5517 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
卡尔特斯11 小时前
Android Kotlin 项目代理配置【详细步骤(可选)】
android·java·kotlin
白鲸开源11 小时前
Ubuntu 22 下 DolphinScheduler 3.x 伪集群部署实录
java·ubuntu·开源
ytadpole11 小时前
Java 25 新特性 更简洁、更高效、更现代
java·后端
纪莫12 小时前
A公司一面:类加载的过程是怎么样的? 双亲委派的优点和缺点? 产生fullGC的情况有哪些? spring的动态代理有哪些?区别是什么? 如何排查CPU使用率过高?
java·java面试⑧股
JavaGuide12 小时前
JDK 25(长期支持版) 发布,新特性解读!
java·后端
用户37215742613512 小时前
Java 轻松批量替换 Word 文档文字内容
java
白鲸开源12 小时前
教你数分钟内创建并运行一个 DolphinScheduler Workflow!
java
Hilaku13 小时前
Token已过期,我是如何实现无感刷新Token的?
前端·javascript·面试