写点什么

大白话讲解 synchronized 锁升级套路

  • 2023-04-28
    湖南
  • 本文字数:1616 字

    阅读完需:约 5 分钟

synchronized 锁是啥?锁其实就是一个对象,随便哪一个都可以,Java 中所有的对象都是锁,换句话说,Java 中所有对象都可以成为锁。这次我们主要聊的是 synchronized 锁升级的套路。


synchronized会经历四个阶段:无锁状态偏向锁轻量级锁重量级锁 依次从耗费资源最少,性能最高,到耗费资源多,性能最差。

锁原理

先看看这些状态的锁为什么称之为锁,他们的互斥原理是啥。

偏向锁

当一个线程到达同步代码块,尝试获取锁对象的时候,会查看对象头中的MarkWord里的线程 ID,如果这里没有 ID 则将自己的保存进去,拿到锁。若是有,则查看是否是当前线程,如果不是,就 CAS 尝试改,如果是,就已经拿到了锁资源。


这里详细说说 CAS 尝试修改的逻辑:它会检查持有偏向锁的线程状态。首先遍历当前 JVM 的所有存活的线程,如果能找到偏向的线程,则说明偏向的线程还存活,此时会检查线程是否在执行同步代码块中的代码,如果是,则升级为轻量级锁,去继续进行 CAS 竞争锁。所以加了偏向锁之后,同时只有一个线程可以拿到锁执行同步代码块中的代码。

轻量级锁

查看对象头中的MarkWord里的Lock Record指针指向的是否是当前线程的虚拟机栈,如果是,拿锁执行业务,如果不是则进行 CAS,尝试修改,若是修改几次都没有成功,再升级到重量级锁。

重量级锁

查看对象头中的MarkWord里的指向的ObjectMonitor,查看 owner 是否是当前线程,如果不是,扔到ObjectMonitor里的EntryList中排队,并挂起线程,等待被唤醒。

锁升级

无锁

一般情况下,新 new 出来的一个对象,暂时就是无锁状态。因为偏向锁默认是有延迟的,在启动 JVM 的前 4s 中,不存在偏向锁,但是如果关闭了偏向锁延迟的设置,new 出来的对象,就会添加一个匿名偏向锁。也就是说这个对象想找一个线程去增加偏向锁,但是没有找到,称之为匿名偏向。存储的线程 ID 为一堆 0000,也没有任何地址信息。


我们可以通过以下配置关闭偏向锁延迟:

//关闭偏向锁延迟的指令-XX:BiasedLockingStartuoDelay=0
复制代码

偏向锁

当某一个线程来获取这个锁资源时,此时会成功获取到,就会变为偏向锁,偏向锁存储线程的 ID。

偏向锁升级时,会触发偏向锁撤销,偏向锁撤销需要等到一个安全点,比如 GC 的时候,偏向锁撤销的成本太高,所以默认开始时,会做偏向锁延迟。若是直接有多个线程竞争,会跳过偏向锁,直接变为轻量级锁。


细说一下偏向锁撤销的过程,成本为啥高呢?当一个线程拿到偏向锁之后,会把锁的对象头的Mark Work中的线程 id 指向自己,当又有一个线程来了进行争抢导致锁升级的的时候,会暂停之前拿到偏向锁的线程,然后清空 Mark Work 中的线程 id增加一个轻量级锁,然后再恢复暂停的线程继续执行。这也是为什么等到安全点再执行锁升级的原因,因为要暂停线程。


常见的安全点:

  • 执行 GC 的时候

  • 方法返回之前

  • 调用某个方法之后

  • 抛出异常的位置

  • 一个循环的末尾

轻量级锁

当在出现了多个线程的竞争,就会升级为轻量级锁,轻量级锁的效果就是基于 CAS 尝试获取锁资源,这里会用到自适应自旋锁,根据上次 CAS 成功与否,耗费的时间,决定这次自旋多少次。


轻量级锁适用于竞争不是很激烈的场景,一个线程拿到锁,执行同步代码块,很快就处理完了。再来一个线程尝试一两次也拿到了锁,再去执行,不会让一个线程等待很久。

重量级锁

如果到了重量级锁,那就没啥说的了,如果有线程持有锁,其他想拿锁的就挂起,等待锁释放后被依次唤醒

锁粗化 &锁消除

锁粗化/锁膨胀

锁膨胀是编译 Java 文件的时候,JIT 帮我们做的优化,它会减少锁的获取和释放次数。比如:

while(){   synchronized(){      // 多次的获取和释放,成本太高,会被优化为下面这种   }}synchronized(){   while(){       //  拿到锁后执行循环,只加锁和释放一次   }}
复制代码

锁消除

锁消除则是在一个加锁的同步代码块中,没有任何共享资源,也不存在锁竞争的情况,JIT 编译时,就直接将锁的指令优化掉。 比如:

synchronized(){   int a = 1;   a++;   //操作局部变量的逻辑}
复制代码


作者:奔跑的毛球

链接:https://juejin.cn/post/7221481997569884218

来源:稀土掘金

用户头像

还未添加个人签名 2021-07-28 加入

公众号:该用户快成仙了

评论

发布
暂无评论
大白话讲解synchronized锁升级套路_做梦都在改BUG_InfoQ写作社区