JVM中的锁优化

Markword格式

在这里插入图片描述

无锁

首先每个实例对象都有一个对象头,对象头中有一个MarkWord记录着对象的hashcode

、年龄以及锁信息

下面是无锁状态的Markword格式

hashcode    |    unused | age | 0 | 01

倒数第三位的0代表没有偏向

偏向锁

Markword格式

threadid | epoch | age | bias |1| 01

倒数第三位的1代表有偏向

偏向锁可以怎么理解呢,偏向就是说这个锁偏袒一个线程, 但只有一个线程的时候使用,它的速度是优于轻量级锁的,因为轻量级锁设计到CAS操作,而偏向锁只需要线程获取对象锁的时候第一次CAS就行。

偏向锁和轻量级锁都适合没有资源竞争的情况,(如果由资源竞争就会发生锁升级)

偏向锁默认情况下是开启的,也可以由UseBiasLocking开关来控制

有几种情况会发生撤销偏向

  1. 当另一个线程B获取锁的时候,发现线程id不对,就会撤销偏向,将偏向锁转为无锁状态,然后线程B偏向锁,用完之后又变为线程A的偏向,该动作称为撤销偏向
  2. 当调用对象的hashCode方法的时候也会撤销偏向,为啥呢,因为偏向锁没有地方可以存hashCode,对象的Markword用来存线程id等内容了。
  3. 当调用wait方法、notify方法的时候会撤销偏向,为啥呢,因为wait和notify适用于重量级锁

偏向锁的优化

  1. 当撤销偏向发生20次后,虚拟机就会认为该对象的偏向线程不正确,对这些对象进行批量重偏向。
  2. 当撤销偏向发生40次后,虚拟机就会批量撤销,自此就关闭了偏向锁,所有初始化的对象都为001的无锁状态。

轻量锁

markword格式

ptr_to_lock_record | 00

在这里插入图片描述

轻量锁通过CAS和锁记录实现,每个线程都有独立的栈帧,但所对应方法去获取对象的锁时,就会通过CAS比较并交换Markword和锁记录的内容,有三种情况。

交换成功:交换域其实是我自己方便理解定义的东西,就是如果上锁成功,交换对象头中markword的内容

锁重入:同一个线程的方法,栈帧中的锁记录指向对象

交换失败:说明存在竞争,锁升级为重量级锁。

重量级锁

markword格式

prt_to_monitor | 10

重量级锁是基于monitor实现的,monitorenter 临界区 monitorexit这样的方式
在这里插入图片描述

第一个获得锁的为Owner,后续竞争锁的进入entryset排序,如果由wait方法阻塞的线程进入waitset等待唤醒。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RuUTNK2T-1690200978978)(attachment:7a51cf586f503c023d32b2ab2b644555)]

自旋锁

就是说进行的线程不会立刻进入entrySet,会现在cpu里面自旋等待一段时间,否则的化又要io浪费时间,但是这种方式也会浪费cpu的时间,适合多核cpu。JVM会对自选设置自定义的阈值,默认10,由JVM去优化,到底自旋多少次合适。

锁消除

不存在对象逃逸的情况下,且没有临界资源,某个线程独占式的访问

锁粗化

同一个线程,同一个临界区,重复进入临界区多次,粗化为进入一次

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值