轻量级锁和偏向锁

JVM的两种改善机制——轻量级锁和偏向锁

轻量级锁

synchronized会在对象的头部打标记,这个加锁的动作是必须要做的,悲观锁通常还会做许多其他的指令动作,轻量级锁希望通过CAS实现,它认为通过CAS尝试修改对象头部的mark区域的内容就可以达到目的,由于mark区域的宽度通常是4~8字节,也就是相当于一个int或者long的宽度,是否适合于CAS操作。

轻量级锁通常会做一下4个步骤:
(1) 在栈中分配一块空间用来做一份对象头部mark word的拷贝,在mark word中将对象锁的二进制位设置为“未锁定”(在32位的JVM中通常有2位用于存储锁标记,未锁定的标记为01),这个动作是方便等到释放锁的时候将这份数据拷贝到对象头部。

(2) 通过CAS尝试将头部的二进制位修改为“线程私有栈中对mark区域拷贝存放的地址”,如果成功,则会将最后2位设置为00,代表已经被轻量级锁锁住了。

(3) 如果没有成功,则判定对象头部是否已经指向了当前线程所在的栈当中,如果成立则代表当前线程已经是拥有着,可以继续执行。

(4) 如果不是拥有着,则说明有多个线程在争用,那么此时会将锁升级为悲观锁,线程进入BLOCKED状态。

JVM发现在轻量级锁里面多次“重入”和“释放”时,需要做的判断和拷贝动作还是很多,而在某些应用程序中,锁就是被某一个线程一直使用,为了进一步减小锁的开销,JVM中出现了偏向锁,偏向锁希望记录的是一个线程ID,它比轻量级锁更加轻量,当再次重入判定时,首先判定对象头部的线程ID是不是当前线程,若是则表示当前线程已经是对象锁的OWNER,无须做其他任何动作。

偏向锁

步骤如下:
(1) 一个线程去争用时,如果没有其他线程争用,则会尝试CAS去修改mark word中一个标记为偏向(mark word单独有一个bit表示是否可偏向,记录锁的位置依然为01),这个CAS动作同时会修改mark word部分bit以保留线程的ID值。

(2) 当线程不断发生重入时,只需要判定头部的线程ID是否是当前线程,若是,则无需任何操作。

(3) 如果同一个对象存在另一个线程发起了访问请求,则首先会判定该对象是否已经被锁定了。如果已经被锁定,则会将锁修改为轻量级锁(00),也就是锁粒度上升了;而如果没有锁定,则会将对象的是否可偏向的位置设置为不可偏向。

偏向锁只是解决了没有任何锁争用的场景,当出现锁争用后它便没有什么用途了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值