synchronized锁升级_升级synchronized锁,提高效率!

1e5666cee71ed379454504a1dbba9197.png

前言

synchronized是Java内置的机制,是JVM层面的,而Lock则是接口,是JDK层面的,尽管最初synchronized的性能效率比较差,但是随着版本的升级,synchronized已经变得原来越强大了,synchronized效率很低,因为底层操作依赖于操作系统,操作系统切换线程要从用户态切换到内核态,花费很多时间。Java SE1.6为了减少获得锁和释放锁带来的性能消耗引入了偏向锁和轻量级锁

下面解析一下synchronized锁升级过程和原理,希望可以帮助到大家!

什么是锁升级

锁一共有四种状态,级别由低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态。这几个状态会随着竞争情况逐渐升级,但是锁可以升级不能降级。一个锁对象刚创建的时候,没有线程调用它,此时处于无锁状态。

对象头

了解锁之前,要先了解对象头,因为锁的实现是依赖对象头中的Mark Word的。根据锁的不同状态,Mark Word的变化如下:

174550e6093958a2d759193ffd0e1ca5.png

其中无锁状态的时候,锁标志位是01,是否是偏向锁是0

偏向锁

偏向锁的含义

大多数情况下,锁不仅不存在多线程竞争,而是总由同一个线程多次获得,为了让线程获得锁的代价更低引入了偏向锁。使用偏向锁就表明这个锁对象只被一个线程调用,可以减少上下文切换。
一个线程获得了偏向锁,再次访问锁对象的时候不需要进行加锁解锁的操作,只需要判断Mark Word里面的Thread ID是否是自己。

偏向锁的实现

当一个线程访问同步块获取锁的时候,先看锁的标志位是不是01(无锁或者偏向锁),在看偏向锁是不是1。是偏向锁就判断Thread ID是不是指向自己,是就进入同步代码块,不是就用CAS替换对象头;无锁状态直接CAS替换对象头。此外,CAS替换对象头(已偏向)时,先将对象变成无锁状态,然后偏向自己

2d5db7a1e24f3f4ee7636189f17b14ce.png
  • 什么时候CAS替换对象头成功?什么时候失败?
    偏向锁的释放不是主动的,持有偏向锁的线程执行完同步代码后不会主动释放锁,要等待其他线程来竞争才会释放锁。如果线程A持有偏向锁,但是已经执行完了同步代码,此时线程B来获取偏向锁,CAS就会成功。当线程A并未执行完同步代码,会出现锁竞争,CAS失败,偏向锁升级为轻量级锁。
    升级为轻量级锁后锁标志位00,原持有偏向锁的线程持有轻量级锁。

轻量级锁

在多线程竞争不激烈的前提下使用轻量级锁,可以减少重量级锁对线程的阻塞带来的开销。其他线程在竞争锁的时候只需要稍微等待(自旋),就可以获取锁。但是自旋次数有限,超过自旋次数限制就会升级为重量级锁。实现
执行同步代码块的时候,JVM会先在当前线程的栈帧中创建存储锁记录的空间(Lock Record),并将对象头的Mard Word复制到锁记录中(Displaced Mark Word),加锁时使用CAS将对象头的Mark Word替换为指向锁记录的指针,解锁时使用原子的CAS操作将Displaced Mark Word替换回对象头。
在获取锁失败时,表示出现锁竞争,该线程尝试使用自旋来获取锁。

bfafb6d1e80d7a14c20966c344978788.png

当自旋超过次数限制或者一个线程持有锁,一个线程在自旋,又来额外的线程尝试获取锁,此时轻量级锁会膨胀成重量级锁

锁升级过程

  • 偏向锁:一个线程进入临界区
  • 轻量级锁:读个线程交替进入临界区
  • 重量级锁:多个线程同时进入临界区
    锁升级过程:

49bb42769543b6c875aa526b596a4853.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值