JVM锁优化

栏目: Java · 发布时间: 5年前

内容简介:锁优化技术(HotSpot虚拟机而言)包括适应性自旋、锁消除、锁粗化、轻量级锁和偏向锁等。这些技术都是为了在线程之间更高效地共享数据以及解决竞争问题,从而提高程序效率。如果线程获取不到锁,第一时间不是去切换系统态进行等待,而是做一个循环操作,去等到锁的释放,循环到一定的次数终止循环,调入系统调用。为了让线程等待,而不是阻塞,让线程执行一个忙循环(自旋),这就是自旋锁。自旋锁的优化主要是为了减少了线程切换带来的消耗。

锁优化技术(HotSpot虚拟机而言)包括适应性自旋、锁消除、锁粗化、轻量级锁和偏向锁等。这些技术都是为了在线程之间更高效地共享数据以及解决竞争问题,从而提高程序效率。

自旋锁

什么是自旋锁?

如果线程获取不到锁,第一时间不是去切换系统态进行等待,而是做一个循环操作,去等到锁的释放,循环到一定的次数终止循环,调入系统调用。为了让线程等待,而不是阻塞,让线程执行一个忙循环(自旋),这就是自旋锁。

为什么消耗CPU而不是等待?

自旋锁的优化主要是为了减少了线程切换带来的消耗。

自旋锁适应的场景

自旋锁适合那些线程占用锁时间短的场景。

什么是自适应自旋锁?

JDK1.6加入了自适应自旋锁。顾名思义,如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行,那么虚拟机就会认为这次自旋也很有可能再次成功,并将自旋等待时间延长。如果对于某个锁,自旋很少成功,那么在之后获取该锁时可能会放弃不自旋直接挂起线程。

锁消除

什么是锁消除?

指虚拟机即时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争时,把锁进行消除。

怎样判断哪些代码可以进行锁消除?

锁消除的主要判断依据来源于逃逸分析的数据支持,如果判断在一段代码中,堆上的所有数据都不会逃逸出去从而被其他线程访问到,那就可以把它们当做栈上数据对待,认为它们是线程私有的,同步加锁就无需进行。

锁粗话

什么是锁粗话?

如果一系列的连续动作都对同一对象反复加锁和解锁,甚至加锁操作时出现在循环体中的,那即使没有线程竞争,频繁地进行互斥同步操作也会导致不必要的性能损耗,比如连续的append()方法。

轻量级锁和偏向锁

在说轻量级锁和偏向锁之前,我们要先了解一下HotSpot虚拟机中对象的对象头。

HotSpot虚拟机的对象头分为两部分信息:

  • 第一部分用域存储对象自身的运行时数据(Mark Word),如哈希码、GC分代年龄等,他是实现轻量级锁和偏向锁的关键。
  • 另一部分用于存储只想方法区对象类型的指针,如果是数组对象,还有一个额外部分存储数组长度。

所以,我们来看一下对象头的Mark Word中的存储内容有哪些?

存储内容 标志位 状态 用处
对象哈希码,对象分代年龄 01 未锁定 状态
指向锁记录的指针 00 轻量级锁定 状态
指向重量级锁的指针 10 膨胀 状态
空,不需要记录信息 11 GC标记 状态
偏向线程ID,偏向时间戳、对象分代年龄 01 可偏向 状态

什么是CAS操作?

CAS是英文单词CompareAndSwap的缩写,中文意思是:比较并替换。简单来说,CAS整个比较并替换的操作是一个原子操作。

轻量级锁

什么是轻量级锁?

他的意思是在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的消耗

轻量级锁的执行过程?

加锁过程:

  • 进入同步块的时候,如果此同步对象没有被锁定(锁标志位为“01”状态),虚拟机首先将在当前线程的帧栈中建立一个名为“锁空间”(Lock Record)的空间,用于存储锁对象目前Mark Word的拷贝(这份拷贝叫Displaced Mark Word)
  • 虚拟机将使用CAS操作尝试将对象的Mark Word更新为指向Lock Record的指针
    • 如果成功,这个线程就有了该对象的轻量级锁,Mark Word的锁标志位变为“00”
    • 如果失败,虚拟机先检查对象的Mark Word是否指向当前线程的栈帧
      • 如果指向当前线程帧栈就说明该线程获取到了该锁,可进入同步块继续执行
      • 若没指向当前线程的帧栈,表示这个锁对象被其他线程占用,这时轻量级锁不再有效,要膨胀为重量级锁,锁的标志位变为“10”,Mark Word 中存储的就是指向重量级锁(互斥量)的指针,后面等待的线程也要进入阻塞状态

解锁过程:

  • 如果对象的Mark Word仍然指向线程的锁记录,就用CAS操作把对象当前Mark Word和线程中复制的Displaced Mark Word替换回来
    • 替换成功,同步完成
    • 替换失败,有其他线程尝试获取该锁,释放锁的同时,唤醒被挂起的线程。

轻量级锁的使用场景

提升程序同步性能的依据是“对于绝大部分的锁,在整个同步周期内都是不存在竞争的”。

如果没有竞争,轻量级锁使用CAS操作避免了使用互斥量的开销。

但如果存在锁竞争,除了互斥量的开销外,还额外发生了CAS操作,因此在有竞争的情况下,轻量级锁会比传统的重量级锁更慢。

偏向锁

什么是偏向锁?

消除数据在无竞争情况下的同步原语,进一步提高程序的运行性能。简单来说就是**在无竞争的情况下把整个同步都消除掉,连CAS操作都不做。**就是说当一个线程率先获取到这个锁后,如果该锁没有被其他线程获取,那么持有偏向锁的线程将永远不需要同步。

工作过程

  • 当锁对象 第一次 被线程获取的时候,虚拟机将会把对象头中的标志位设为"01",使用CAS操作把获取到的锁的线程ID记录到Mark Word中,如果CAS操作成功,持有偏向锁的线程以后每次进入这个锁相关的同步块时,都不再进行任何操作
  • 当有另一个线程去尝试获取这个锁时,偏向模式宣告结束。根据锁对象目前是否处于被锁定的状态,撤销偏向后恢复到未锁定或轻量级锁定的状态,后续的同步操作就如上面介绍的轻量级锁那样执行

偏向锁的使用场景

可以提高带有同步但无竞争的程序性能

和轻量级锁一样,如果这个同步块可能很多时候都是多个线程同时访问的话,那么偏向锁甚至会增加时耗

总结

JVM对锁进行了优化,包括自旋锁(自适应自旋锁)、锁粗化、轻量级锁、偏向锁。而后两者会因为竞争的多少而产生性能的变化。


以上所述就是小编给大家介绍的《JVM锁优化》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

产品心经

产品心经

闫荣 / 机械工业出版社 / 2014-9-30 / 59

产品经理如何才能迅速地、全方位地提升自己的能力,从而打造出让用户尖叫并疯狂爱上的产品?有没有捷径?从成功的、有经验的产品经理的实践真知和智慧中学习是一个很好的途径!本书就是一位拥有近10年产品经验的资深产品经理的实践真知和智慧的结晶,从产品经理核心素养、产品认知、战略与规划、精益开发、需求分析与管理、用户体验、精细运营7大方面,系统梳理了能全面、迅速提升产品经理能力,从而打造出让用户尖叫的产品的5......一起来看看 《产品心经》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具