JVM锁优化

时间:2021-01-29 09:05:23

1. 概述

  JDK1.6版本花费了大量精力去实现各种锁优化,如适应性自旋,锁消除,锁粗化,轻量级锁,偏向锁等,这些技术都是为了在线程期间更高效的共享数据,以及解决竞争问题。

2. 自旋锁与自适应自旋

  传统的互斥锁对性能最大的影响是阻塞的实现,线程的挂起和恢复需要转入内核态中完成,相当影响效率。

  多线程场景下线程之间通过抢占CPU时间分片进行任务执行,有可能持有锁的线程很快就会释放锁,此时让后面的线程执行一个忙循环进行等待。这就是自旋锁。

  自选次数默认为10次,可使用 -XX:PreblockSpin参数来更改。

  jdk1.6 加入了自适应自旋锁,这意味着自旋时间不再是固定的,而是由上一次在同一个锁上的自旋时间及锁的拥有者状态来决定。随着JVM的运行,自旋时间的预测也将更加准确。

3. 锁消除

  锁消除是指在JVM即时编译器运行时,在对代码进行同步时,对检测到不存在共享数据竞争的锁进行消除。

4. 锁粗化

  如果一系列的连续操作都对同一个对象反复加锁和解锁,则将会把同步的范围粗化到整个操作序列的外部,这样只需要加一次锁就行了。

5. 偏向锁

  目的:在无竞争的情况下消除整个同步使用的互斥量,连CAS操作都不做了。

  定义:偏向锁会偏向第一个获得它的线程,如果在接下来的执行过程中该锁没有被其他线程获取,则持有偏向锁的线程以后进入这个锁相关的同步块不再需要进行同步。

  原理:

  1. 锁对象第一次被获取时,虚拟机会把,即偏向锁模式;
  2. 同时使用CAS操作将线程ID记录在对象的 Mark World 之中;
  3. 若CAS操作成功,则以后进入这个锁相关的同步块时不再进行任何同步操作。

  当另一个线程尝试获取这个锁时,偏向模式结束。此时根据锁对象是否处于锁定状态,将锁对象恢复到未锁定状态或者轻量级锁状态(锁的升级,单向不可逆)。

6. 轻量级锁

  目的:在无竞争的情况下使用CAS操作去消除同步使用的互斥量;

  原理:

  1. 代码进入同步块的时候,若锁对象没有被锁定。
  2. 虚拟机首先在栈帧中建立一个名为锁记录(Lock Record)的空间,存储锁对象的 Mark World 的拷贝;
  3. 虚拟机使用CAS操作将对象的 Mark World 更新为指向 Lock Record 的指针;
  4. 若这个CAS操作成功,则此对象处于轻量级锁定状态;
  5. 若这个CAS操作失败,则检查对象的 Mark World 是否已经指向当前线程栈帧中的 Lock Record,
  6. 若已经指向,则表明当前线程拥有该对象的锁,继续执行,否则膨胀为重量级锁。