ConcurrentPrograming——轻量级与偏向锁之间的转换

文章目录



一、执行流程

在这里插入图片描述
偏向锁执行流程

在这里插入图片描述
偏向状态
在这里插入图片描述
一个对象创建时:
1、如果开启了偏向锁(系统默认开启),那么对象创建后,markwork后三位值为101,这是对象前面的分代年龄、thread的id、epoch等都为空,只有在第一次使用时才会赋值(正常状态下即使创建了对象也不会有hashCode,只有使用到此对象才会生成hashCode等信息)。
2、偏向锁在JAVA中会产生延迟,一般在对象创建时不会立马见效,要等那么个三四秒再打印时才能可以看到偏向状态,如果避免延迟,可以jvm参数。

下面例子(取消了偏向锁延迟)第一个输出可以看出一开始后3位为101表明默认开启了偏向锁此时,且此时没有线程id、分代年龄等信息,第二条输出可以看到后三位仍是101说明处于偏向锁状态,且前面不为空,此时有了线程id、分代年龄等信息,第三条输出,此时还是101(因为默认101),解锁后前面的信息仍不为空,表明偏向锁的特性,线程使用完偏向锁后,偏向锁会记录线程id等信息,即使是解锁之后,表明此对象为此id的线程专属,正常情况下其他锁释放后,前面的内容会清空而偏向锁不会,还记录着线程的ID表明偏向的特性 。
在这里插入图片描述
当一个可偏向的对象,调用hashCode方法时,就会撤销可偏向的状态,因为(偏向状态时MarkWork里面没有hashCode的信息,所以只能是normal,加锁时也只能加轻量级锁,为什么轻量级锁和重量级锁不会有此现象,因为轻量级锁把对象的hashCode存储在LockRecord中,而重量级锁把对象的hashCode存储在了Monitor中,将来解锁时都会还原回来,但是对于偏向锁没有额外的存储空间了,因此调用hashCode会让处于偏向状态的对象变成不可偏向的normal对象)。

撤销可偏向状态(偏向锁失效)
调用对象hashCode方法,加锁时也是加轻量级锁。
多个线程访问同一个偏向锁对象,偏向锁失效,撤销偏向锁并升级为轻量级锁。调用wait、notify(因为wait、notify只有重量级锁才有,不管是轻量级锁还是偏向锁都会升级为重量级锁)。

批量重偏向
如果对象虽然被多个线程访问,但没有竞争,这是偏向了线程t1的对象仍有机会重新偏向t2,重偏向会重值对象的ThreadID

当撤销偏向锁阈值超过了20次后,jvm会觉得可能字节偏向错了,于是会给这些对象加锁时重新偏向至加锁线程。即原本偏向t1的对象,被撤销并升级为轻量级锁,解锁后为normal状态,此流程执行20次后会直接偏向为另一个线程。

批量撤销
当撤销偏向锁阈值超过40后,jvm觉得自己错了,不需要重偏向,于是整个类的所有对象都会变成不可偏向的,新建的对象也是不课偏向的。

锁消除
JIT(即时编译器)进行优化,对那些没有逃逸的或共享变量,会把synochronized去掉。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值