Synchronized锁升级过程

Synchronized锁升级过程

锁在jdk1.6之前只有两种状态:无锁和有锁两种状态,在jdk1.6之后,对synchronized进行了优化,增加了两种状态,现在锁一共有四种状态:无锁、偏向锁、轻量级锁、重量级锁。

无锁也是一种状态,锁的类型和状态存在对象头的MarkWord中,在申请锁、锁升级等过程中JVM都需要读取对象的MarkWord中的数据。

偏向锁

为什么要引入偏向锁呢?

因为进过HotSpot的作者大量的研究发现,大多数情况下,锁不仅不存在多线程竞争,而且总是由同一个线程多次获得,为了让线程获得锁的代价更低,而引入了偏向锁。

偏向锁的升级

当线程a访问同步块并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的锁的ThreadID,以后在线程进入和退出代码块时,不需要进行CAS操作进行加锁和解锁,只需要简单测试一下对象头的MarkWord中是否存储着指向当前线程的ThreadID

  • 如果有的话,还是线程a获取锁。
  • 如果没有的话,则需要查看对象头的MarkWord中指向的线程是否存活:
    • 如果没有存活,那么锁对象被重置为无锁状态,其他线程可以竞争并将其设置为偏向锁;
    • 如果存活,需要查找该线程(MarkWord中指向的线程)的栈帧信息,如果该线程还需要继续获得锁,那就暂停该线程,撤销偏向锁,升级为轻量级锁;如果该线程不在需要获得锁,那就将锁对象状态设置为无锁状态,重新偏向新的线程。

举个例子:

假设有两个线程,线程a,线程b,两个线程都要执行一个同步代码块(或方法),当线程a先访问同步代码块,会在对象头和栈帧中锁记录里存储线程a的线程id,以后在线程a进入和退出代码块时,只需要对象头中记录的线程id是否是线程a的线程id,然后就可以继续获取锁;这时当线程b访问同步方法时,它也会判断对象头中存储的线程id是否和线程b的线程id相同,因为对象头存储的是线程a的id,所以肯定不相同,接着就查看线程a是否存活,我们假设线程a还没有结束,那线程a肯定还是存活的,然后就查看线程a的栈帧信息,因为线程a,b是交替执行的,所以线程a还需要继续获得锁,那这就会暂停线程a,撤销偏向锁,将锁升级为轻量级锁。

轻量级锁

轻量级锁考虑的是竞争锁对象的线程不多,而且线程持有锁的时间也不长的情景。因为阻塞线程需要CPU从用户态转换到内核态,代价很高,如果线程刚阻塞不就锁就被释放了,那就有点得不偿失,因此这时候,就选择不阻塞线程,而是让它自旋等待锁的释放。

轻量级锁升级为重量级锁

线程1获取轻量级锁时,会把锁对象的对象头MarkWord复制一份到线程1的栈帧中用于存储锁记录的空间(称为DisplacedmarkWord),然后使用CAS把对象头中的内容替换为线程1存储的锁记录地址。

如果线程1复制对象头的同时(在线程1CAS之前),线程2也准备获取锁,复制了对象头到线程2的锁记录空间中,但是线程2CAS的时候,发现线程1已经把对象头换了,线程2就会使用自旋来等待线程1释放锁。

但是如果自旋的时间太长,就会影响性能,因为自旋需要消耗CPU,所以需要对自旋的次数进行限制,可以是10次,可以是100次,当超过了自旋次数线程1仍没有释放锁,或者线程1还在执行,线程2还在自旋等待,这时又有一个线程3来竞争这个锁,那这个时候轻量级锁就会升级为重量级锁。重量级锁就会把除了拥有锁的线程都阻塞,防止CPU空转。

轻量级锁一旦升级为重量级锁,就不会再降级为轻量级锁了,偏向锁升级为轻量级锁后也不能在降级为偏向锁。锁可以升级但不能降级,但是偏向锁可以被重置为无锁状态。

synchronized的执行过程

  • 检测Mark Word里面是不是当前线程的ID,如果是,表示当前线程处于偏向锁
  • 如果不是,则使用CAS将当前线程的ID替换Mard Word,如果成功则表示当前线程获得偏向锁,置偏向标志位1
  • 如果失败,则说明发生竞争,撤销偏向锁,进而升级为轻量级锁。
  • 当前线程使用CAS将对象头的Mark Word替换为锁记录指针,如果成功,当前线程获得锁
  • 如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。
  • 如果自旋成功则依然处于轻量级状态。
  • 如果自旋失败,则升级为重量级锁。

锁的优缺点的对比

img

参考文章:(3条消息) synchronized底层原理以及锁升级过程_Fking’s Blog-CSDN博客_synchronize底层原理及锁的升级

(3条消息) Java并发——Synchronized关键字和锁升级,详细分析偏向锁和轻量级锁的升级_tongdanping的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值