synchronized锁升级过程(无锁->偏向锁->轻量级锁->重量级锁)

synchronized锁升级过程(无锁->偏向锁->轻量级锁->重量级锁)

锁的级别从低到高:无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁

首先,我们来看一下Java对象的组成结构:对象头+成员变量
在这里插入图片描述
其中Mark Word结构为:biased_lock表示是否为偏向锁,age表示对象在新生代中经历垃圾回收的次数。如果为偏向锁,那么thread参数表示该线程id对应的线程拥有这把锁
在这里插入图片描述
一个对象创建时:

  • 如果开启了偏向锁(默认开启),那么对象创建后,markword值为0x05即最后3位为101,这时它的thread,epoch,age都为0

  • 偏向锁是默认是延迟的,不会在程序启动时立即生效,如果想避免延迟,可以加VM参数

-XX:BiasedLockingstartupDelay=0 来禁用延迟

  • 如果没有开启偏向锁,那么对象创建后,markword值为0x01即最后3位为001,这时它的hashcode,age都为0,第一次用到hashcode时才会赋值

当锁处于偏向状态时,锁的对象头thread字段会写入偏向的线程id,这个时候如果不存在多个线程的竞争,该线程在后续的执行中自动获取锁,降低获取锁带来的性能开销,偏向锁,指的就是偏向第一个加锁线程,该线程不会主动释放偏向锁,只有当其他线程尝试竞争锁的时候才会被释放。

假设锁偏向线程A,这个时候线程B来尝试获取锁,如果检测到线程A终结,那么就会将锁修改为无锁状态,线程B拿到锁并将其偏向为自己。如果检测到线程A还存活,此时暂停线程A,并将偏向锁升级为轻量级锁,线程B会通过自旋的形式尝试获取锁,线程不会被阻塞。当自旋超过一定的次数,或者在(一个线程持有锁,另一个线程在自旋,此时又有第三个线程来访)时,轻量级锁也会升级为重量级锁。

轻量级锁升级为重量级锁的过程:

每个线程的栈帧都会包含一个锁记录的结构,内部可以存储锁定对象的Mark word ,并且记录锁对象的引用地址。而锁的mark word则会指向指向栈帧内的锁记录。
每当有线程要加轻量级锁时,会做一个cas替换,将锁对象的mark word 保存至Lock record 里面。

如果cas成功,表示加锁成功
如果cas失败,有两种情况:

  • 其他线程已经持有了该Object的轻量级锁,表明有竞争,进入锁膨胀过程(轻量级锁升级为重量级锁)。
  • 发生了锁重入,这个时候再添加一个Lock record 作为重入的计数

重量级锁通过对象内部的监视器monitor实现,锁对象的对象头会关联一个对象监视器,当其他线程尝试去获取锁,但是检测到该锁对象已经关联到了对象监视器的时候,就会阻塞。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值