Syschronized锁升级

5 篇文章 0 订阅
3 篇文章 0 订阅

Syschronized锁升级

锁的4中状态:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态(级别从低到高)

1.偏向锁

1.1.为什么要引入偏向锁?

因为经过HotSpot的作者大量的研究发现,大多数时候是不存在锁竞争的,常常是一个线程多次获得同一个锁,因此如果每次都要竞争锁会增大很多没有必要付出的代价,为了降低获取锁的代价,才引入的偏向锁。

1.2.偏向锁的升级

如果虚拟机启用了偏向锁(启用参数:-XX:+UseBiasedLocking),当锁对象第一次被线程获取时,虚拟机会将Mark Word 的标志位设为"01",即偏向模式。

同时使用CAS 操作把获取到的锁的线程ID记录在对象的Mark Word 之中,如果CAS 操作成功,持有偏向锁的线程无需再进行同步操作。

如果另外一个线程去尝试获取锁,偏向锁就宣告结束。根据锁对象当前是否处于锁定状态

没有锁定 -> 恢复到无锁状态,锁定 -> 升级为轻量级锁

1.3.偏向锁的取消

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

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

2.轻量级锁

2.1.为什么要引入轻量级锁?

轻量级锁的本意是在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗。因为重量级锁对性能最大的影响是阻塞的实现,阻塞实现需要将CPU从用户态转换为内核态,性能开销大。

2.2.自旋锁、自适应自旋锁

  • 2.2.1.自旋锁

两个线程同时执行,后请求锁的线程稍等一下,不放弃处理器执行时间,进行一个忙循环(自旋),默认自旋10次(使用参数 -XX:PreBlockSpin 来进行修改),自旋锁的开启参数为:-XX:UseSpinning

  • 2.2.2.自适应自旋锁

如果同一个锁对象上,自旋等待刚成功获得过锁,并且持有锁的线程正在运行中,那么虚拟机认为这次自旋大概率也会成功,并允许自旋等待更长时间,比如循环100次。但是,如果对于某个锁,很少自旋获得到锁,那么在以后获取这个锁直接略掉自旋的过程。

2.3.轻量级锁的升级

虚拟机首先将当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的Mark Word的拷贝(官方将这份拷贝加了一个Displaced前缀 - Displaced Mark Word,即被取代的)。

虚拟机将使用 CAS 操作尝试将对象的Mark Word 更新为指向 Lock Record 的指针,成功则将对象锁标志位(Mark Word 的最后2bit)转变为"00",轻量级锁加锁成功;

如果CAS 更新操作失败,虚拟机将检查对象的Mark Word 是否指向当前线程的栈帧。如果当前线程已经拥有这个对象的锁,就可以直接进入同步代码块继续执行;否则没有获取锁,线程将使用自旋锁、自适应自旋锁来等待锁释放

如果锁没有释放,自旋次数到了,则膨胀为重量级锁;或者锁没有释放,自旋次数还没到,又来了一个线程,也会膨胀为重量级锁。

3.重量级锁

重量级锁把除了拥有锁的线程都阻塞,等待锁的释放再继续执行。

注意

为了避免无用的自旋,轻量级锁一旦膨胀为重量级锁就不会再降级为轻量级锁了;偏向锁升级为轻量级锁也不能再降级为偏向锁。一句话就是锁可以升级不可以降级,但是偏向锁状态可以被重置为无锁状态。

参考:
1.《深入理解java虚拟机》 – 周志明
2.https://blog.csdn.net/tongdanping/article/details/79647337

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值