synchronized 底层实现原理是什么?什么是锁的升级, 降级?

640?wx_fmt=jpeg

synchronized 的底层是由一对 monitorenter/monitorexit 指令实现的,Monitor 对象是同步的基本实现单元。

Java 6 之前,Monitor 的实现完全是依靠操作系统内部的互斥锁来实现的,这种机制需要进行用户态到内核态的切换,所以在 Java 6 之前,同步都是无差别的重量级操作。

之后的 jdk 中做了优化,提供了三种不同的 Monitor 实现,分别是:

  • 1.偏斜锁 (Biased Locking)

  • 2.轻量级锁

  • 3.重量级锁

所谓锁的升级,降级,实际上是 JVM 对 synchronized 优化的一种策略,JVM 会检测不同的竞争状态,然后自动切换到合适的锁实现,这种切换就是锁的升级,降级。

当没有出现锁的竞争时,默认使用的是偏斜锁。JVM 会利用 CAS 操作,在对象的头上的 Mark Word 部分设置线程 ID, 用来表示当前对象偏向于当前线程,所以并不涉及真正的互斥锁。这种策略是基于现实很多应用场景中,大部分对象生命周期最多会被一个线程锁定,使用偏斜锁可以降低无竞争锁的开销。

如果有另一个线程试图锁定某个以被加持偏斜锁的对象时,JVM 就需要撤销偏斜锁,并切换到轻量级锁实现。轻量级锁依赖 CAS 操作 Mark World 来试图获取锁,如果获取成功,就使用轻量级锁,否者,进一步升级到重量级锁。

题外话 1:网上有很多观点这样说,Java 不会进行锁的降级。

这种观点实际上错误的,锁的降级确实会发生。当 JVM 进入安全点时,会检查是否有闲置的 Monitor, 让后试图进行锁的降级。


补充知识点:

自旋锁

何为自旋锁?竞争锁失败的线程,并不会真实的在操作系统层面被挂起,JVM 会让线程做几个空循环(基于预测在短时间内能够获取到锁),经过若干次循环后,如果可以获取到锁,那么会进入到临界区,如果还不能获取到锁,才会真实在操作系统层面被挂起。

适用场景:

自旋锁可以减少线程的阻塞,这对于锁竞争不是很激烈,且占用锁时间非常短的代码来说,将会带来很大的性能提升,因为自旋的消耗会小于线程被挂起带来的消耗。

但是如果锁竞争激烈,或者持有锁的线程运行时间很长,就不适用于使用自旋锁了,应为自旋锁在获取到锁前一直都是占用 CPU 做无用功,线程自旋的消耗就大于线程被挂起带来的消耗了,造成 CPU 的浪费。

总结:自旋锁实际上是对乐观情况的优化。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值