synchronized锁升级原理

synchronized锁升级原理

锁升级过程主要依赖 Mark Word 偏向锁标志位锁标志位

  • 偏向锁:Mark Word存的是偏向的线程id
  • 轻量级锁:Mark Word存的是指向线程栈中Lock Record的指针
  • 重量级锁:Mark Word存的是指向堆中的monitor对象的指针

锁升级过程

锁升级过程其实就锁从偏向锁到轻量级锁再到重量级锁的过程。

举个例子:

  • 线程1已经获取到锁,此时线程2来抢该对象的锁,由于线程1已经获取到锁,此时这锁已经是偏向锁
  • 线程2开始抢夺该对象的锁,但是发现对象头Mark Word中存储的线程ID是属于线程1的,线程2就会进行cas操作希望获得锁;
  • 此时线程2操作有两种结果:1、获得锁成功:Mark Word中的线程ID替换成线程2的ID,此时锁偏向于线程2,该锁还是偏向锁。2、获取锁失败:则偏向锁就会升级成轻量级锁。此时轻量级锁仍属于线程1持有,继续执行其同步代码。而竞争线程2通过自旋等待获取锁。
  • 自旋次数到了线程1还没有释放锁,或者线程1还在执行,线程2还在自旋等待,这时又有一个线程3过来竞争这个锁对象,那么这个时候轻量级锁就会膨胀重量级锁。重量级锁把除了拥有锁的线程都阻塞,防止CPU空转(自旋的时间太长也不行,因为自旋是要消耗CPU的,因此自旋的次数是有限制的,比如10次或者100次)。

偏向锁

单线程竞争,当线程A第一次竞争到锁时,通过操作修改Mark Word中的偏向线程ID、偏向模式。

偏向锁只有遇到其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁,线程是不会主动释放偏向锁的。

轻量级锁

多线程竞争,但是任意时刻最多只有一个线程竞争,即不存在竞争太过劲烈的情况,也就没有线程阻塞。

升级时机

当关闭偏向锁功能多线程竞争偏向锁会导致偏向锁升级为轻量级锁

加锁

JVM会为每个线程在当前栈桢中创建锁记录的存储空间(即:Displaced Mark Word),若一线程获取锁是发现是轻量级锁。会把锁的 Mark Word复制到自己Displaced Mark Word中。然后线程尝试用cas将锁的Mark Word替换成指向锁记录的指针。如果成功则获取锁,如果失败,表示Mark Word已经被替换成别的线程的锁记录。说明锁竞争。当前线程通过自旋获取锁。

锁释放

释放锁时,当前线程会使用cas操作会将Displaced Mark Word内容复制到Mark Word中。如果没有竞争,锁会释放成功。如果锁由于自旋次数到了或者有其他线程竞争而升级成重量级锁,cas操作会失败,释放锁时同时唤醒阻塞线程。

与偏向锁区别

轻量级锁每次退出同步块都需要释放锁,而偏向锁是在竞争发生时才释放锁。

重量级锁

基于Monitor对象实现的。monitor enter指令获取锁,monitor exit指令释放锁。

总结

synchronized锁升级的过程:先自旋,不行再阻塞。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值