Java面试-锁升级

转载自:java并发相关(二)—— Synchronized的锁升级机制

 

java中synchronize锁分为以下四个阶段:

  • 无锁
  • 偏向锁
  • 轻量级锁
  • 重量级锁

其中偏向锁和轻量级锁是从java1.6开始引入。各阶段之间的切换,如下图:

 

 

二、Synchronized的锁升级机制

  2.1、无锁到偏向锁:

  我们知道,Synchronized修饰的方法被调用前,其对象初始状态是处于无锁状态的,其锁标记位为01,此时当线程a调用此方法时,会通过CAS自旋,替换mark words。

偏向锁是默认开启的,而且开始时间一般是比应用程序启动慢几秒,如果不想有这个延迟,那么可以使用-XX:BiasedLockingStartUpDelay=0;

如果不想要偏向锁,那么可以通过-XX:-UseBiasedLocking = false来设置;

 

   2.2、偏向锁到偏向锁:

  由于偏向锁线程1获取锁后,不会主动修改对象头,所以哪怕此线程1实际已消亡,之前加锁对象的对象头还是保持偏向锁状态。这个时候线程2想要进入同步方法,他会去查看线程1是否还存活,如果已经消亡,则把锁定对象的对象头恢复成无锁,然后重复无锁->偏向锁的过程。

  同时如果线程1未消亡,但是其栈帧信息中不在需要此持有这个锁对象,也会进行一次偏向锁->偏向锁的过程。

 

  2.3、偏向锁到轻量级锁:

  在2.2的情况中,如果线程2需要进入同步方法,线程1还持有这个对象,那么就会进入偏向锁->轻量级锁的过程。此时线程2进行cas替换失败,会修改对象头,升级为轻量级锁,同时开启自旋,重复尝试替换。

 

  2.4、轻量级锁到重量级锁:

  轻量级锁替换失败到达一定次数(默认为10)后,轻量级锁升级为重量级锁。

  需要注意,如果线程2自旋期间,有线程3也需要访问同步方法,则立刻由轻量级锁膨胀为重量级锁

 

  java1.6中,引入了自适应自旋锁,自适应意味着自旋 的次数不是固定不变的,而是根据前一次在同一个锁上自旋的时间以及锁的拥有者的状态来决定。 如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行中,那么虚拟机就会认为这次自 旋也是很有可能再次成功,进而它将允许自旋等待持续相 对更长的时间。

 

posted @ 2020-07-15 11:15  垫底研究生小莫  阅读(530)  评论(0编辑  收藏  举报