面试题——多线程中synchronized锁的升级流程

synchronized锁升级原理

简单版

在锁对象的对象头里面有一个 threadid 字段,在第一次访问的时候threadid 为空,jvm 让其持有偏向锁,并将threadid设置为其线程id,再次进入的时候会先判断threadid是否与其线程id一致。

如果一致则可以直接使用此对象,如果不一致,则升级偏向锁为轻量级锁,通过自旋循环一定次数来获取锁,执行一定次数之后,如果还没有正常获取到要使用的对象,此时就会把锁从轻量级升级为重量级锁,此过程就构成了 synchronized 锁的升级。

详细版

  1. 对象没有被当做锁的时候,为普通对象,Mark Word锁标志位为01,偏向锁位为0,呈现无锁状态

  2. 线程A要执行同步锁的代码时,该对象被当做同步锁,线程抢到该锁时,该对象的对象头当中Mark Word字段中的锁标志位为01,偏向锁位为1,前23位记录线程A的ID,升级为偏向锁

  3. 线程A再次试图获得锁时,检测锁对象的Mark Word里面是不是线程A的ID

    • 如果是,表示线程A获得该偏向锁,可以执行同步锁的代码

    • 如果不是,则使用CAS尝试替换偏向锁Mark Word中的线程ID

      • 如果成功则表示当前线程获得偏向锁

      • 如果失败,则说明发生竞争,对象锁撤销偏向锁,进而升级为轻量级锁(这时对象锁的Mark Word不再保存线程ID,而是保存占有该锁线程的锁记录指针),锁标志位改为00。进入4

  4. 当前线程不断自旋通过CAS尝试将对象锁的Mark Word替换为自己的锁记录指针(当前线程的栈中开辟一块单独的空间,里面保存指向对象锁Mark Word的指针)

    • 如果成功,当前线程获得轻量锁

    • 如果失败,当前线程继续自旋来获取锁

      • 如果自旋成功,则获取轻量锁。

      • 如果自旋失败(自旋超过默认的10次或者自旋等待线程超过CPU线程的二分之一),JVM向操作系统申请一个监视器对象,对象锁的Mark Word中锁标志位改为10,其他区域改为监视器指针,升级为重量锁。进入5

  5. 重量锁生成等待队列,未抢到锁的线程都进入等待队列

锁升级的目的

锁升级是为了减低了锁带来的性能消耗。在Java 6 之后优化 synchronized 的实现方式,使用了偏向锁升级为轻量级锁再升级到重量级锁的方式,从而减低了锁带来的性能消耗。

参考

  1. 面试高频问题:JAVA的锁升级_锁升级面试_进击的波仔的博客-CSDN博客
  2. 三分钟了解synchronized锁升级过程
  3. 详细了解 Synchronized 锁升级过程 - 腾讯云开发者社区-腾讯云 (tencent.com)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值