美文网首页
Java 锁粗化与循环

Java 锁粗化与循环

作者: ApesKingMan | 来源:发表于2021-03-10 07:42 被阅读0次

            Java的锁粗化与循环。

1. 问题

    Hotspot 确实进行了锁粗化优化,可以有效合并几个相邻同步块,从而降低锁开销。能够把下面的代码:

转化为:

问题来了,Hotspot 能否对循环进行这种优化?例如,把:

优化成下面这样?

理论上,没有什么能阻止我们这样做,甚至可以把这种优化看作只针对锁的优化,像 loop unswitching 一样。然而,缺点是可能把锁优化后变得过粗,线程在执行循环时会占据所有的锁。

注:Loop unswitching 是一种编译器优化技术。通过复制循环主体,在 if 和 else 语句中放一份循环体代码,实现将条件句的内部循环移到循环外部,进而提高循环的并行性。由于处理器可以快速运算矢量,因此执行速度得到提升。

2. 实验

        最简单的办法就是找到 Hotspot 优化的证据。幸运的是,有了 JMH 帮助这项工作变得非常简单。JMH 不仅在构建基准测试时有用,并且在分析基准测试方面同样好用。让我们从一个简单的基准测试开始:

有一些重要的技巧

1)使用 -XX:-UseBiasedLocking 禁用偏向锁(Biased Lock)可以避免启动时间过长。由于偏向锁不会立即启动,在初始化阶段要等待5秒钟(参见 BiasedLockingStartupDelay 选项)。

2)禁用 @Benchmark 方法内联操作可以帮助我们从反汇编中分离相关内容。

3)加上“魔数” 0x42 有助于快速从反汇编中定位加法操作。

        注:偏向锁(Biased Locking)。尽管 CAS 原子指令相对于重量级锁来说开销比较小,但还是存在非常可观的本地延迟,为了在无锁竞争的情况下避免取锁获过程中执行不必要的 CAS 原子指令提出了偏向锁技术。

        运行环境 i7 4790K、Linux x86_64、JDK EA 9b156:

        运行数据能分析出什么结果?什么都看不出来,对吧?我们需要调查背后到底发生了什么。这时 -prof perfasm 配置可以派上用场,它能显示生成代码中的热点区域。用默认设置运行,能够发现最热的指令是加锁 lock cmpxchg(CAS),而且只打印指令附近的代码。-prof perfasm:mergeMargin=1000 配置可以将这些热点区域合并保存为输出片段,乍看之下可能觉得有点恐怖。

        分析得出连续的跳转指令是锁定或解锁,注意循环次数最多的代码(第一列),可以看到最热的循环像下面这样:

循环似乎被展开了4次,然后这4个迭代中实现锁粗化!为了排除循环展开对锁粗化的影响,我们可以通过-XX:LoopUnrollLimit=1 配置裁剪循环展开,再次量化受限后的粗化性能。

        性能提升了4倍!显而易见的,因为我们已经观察到最热的指令是加锁 lock cmpxchg。当然,4倍后的粗化锁意味着4倍吞吐量。非常酷,我们是不是可以宣布成功,然后继续前进?还没有。我们必须验证禁用循环展开真正提供了我们想要进行比较的内容。perfasm 的结果似乎表明它含有类似的热点循环,只是跨了一大步。

检查都OK。

3. 观察结果

        当锁粗化在整个循环中不起作用时,一旦中间看起来好像存在 N 个相邻的加锁解锁操作,另一种循环优化——循环展开会提供常规锁粗化。这将提高性能,并有助于限制粗化的范围,以避免长循环过度粗化。

相关文章

  • Java 锁粗化与循环

    Java的锁粗化与循环。 1. 问题 Hotspot 确实进行了锁粗化优化,可以有效合并几个相邻同步块,从而降...

  • Java锁粗化和锁消除

    锁粗化 通常情况下,为了保证多线程间的有效并发,会要求每个线程持有锁的时间尽可能短,但是大某些情况下,一个程序对同...

  • 锁消除 与 锁粗化

    锁消除 如上图示例, object在方法外部, 此为正常的同步方法. 若将Object object =new O...

  • 【译】JVM Anatomy Park #1: 锁粗化与循环

    原文地址:JVM Anatomy Park #1: Lock Coarsening and Loops 问题 众所...

  • 3.3 锁粗化

    原则上,我们在编写代码的时候,总是推荐将同步块的作用范围限制得尽量小——只在共享数据的实际作用域中才进行同步,这样...

  • 锁优化(2)--- 锁粗化

    原则上,我们在编写同步块的时候,同步块的范围应当尽量小——只在共享数据的实际作用域中才进行同步,这样是为了使得需要...

  • java并发-独占锁与共享锁,公平锁与非公平锁,重入锁与非重入锁

    java并发-乐观锁与悲观锁,独占锁与共享锁,公平锁与非公平锁,重入锁与非重入锁 java 中的锁 -- 偏向锁、...

  • 什么是锁粗化?

    在遇到一连串地对同一锁不断进行请求和释放的操作时,把所有的锁操作整合成√锁的一次请求,从而减少对锁的请求同步次数,...

  • JAVA锁相关

    Java锁的概念 自旋锁循环抢锁,是指当一个线程在获取锁的时候,如果锁已经被其它线程抢占,那么该线程将循环等待,然...

  • 关于synchronized的锁升级自旋问题

    1.6之后对synchronized做了优化,包括锁消除、锁粗化、自旋和锁升级的过程:偏向锁、轻量级锁、重量级锁。...

网友评论

      本文标题:Java 锁粗化与循环

      本文链接:https://www.haomeiwen.com/subject/gqwrvhtx.html