synchronized 原理(锁升级、锁消除和锁粗化)

目录:

一、前言
二、锁升级
三、锁消除
四、锁粗化

一、前言

根据之前的锁策略,可以总结出, synchronized 具有以下特性( JDK 1.8):

1. 开始时是乐观锁, 如果锁冲突频繁, 就转换为悲观锁。

2. 开始是轻量级锁实现, 如果锁被持有的时间较长, 就转换成重量级锁。

3. 实现轻量级锁的时候可能用到的是自旋锁策略

4. 是一种不公平锁

5. 是一种可重入锁

6. 不是读写锁

对于synchronized来说,多个线程,针对同一个对象加锁,就会产生阻塞等待,synchronized 内部其实还有一些优化机制,存在的目的就是为了让这个锁更高效,更好用。

二、锁升级

在加锁之前是无锁状态,在进行加锁的时候,首先会进入到偏向锁状态(偏向锁,并不是真正的加锁,而是相当于占了一个位置,有需要的才去真正的加锁,没有需要就不加锁了)。偏向锁的这个过程,有点相当于“懒汉模式”的懒加载差不多,“非必要,不加锁”。

进入sychronized的时候,并不是真的加锁,先处在偏向锁状态,做个标记(这个过程是非常轻量的)。

如果整个使用锁的过程中,都没有出现锁竞争,在synchronized执行完之后,取消偏向锁,回到无锁状态。但是,如果使用过程中,另一个线程也尝试加锁,那么在它加锁之前,迅速的把偏向锁升级成真正的加锁状态!!!另一个线程也就只能阻塞等待了。

当synchronized发生锁竞争的时候,就会从偏向锁,升级成轻量级锁。此时, synchronized相当于是通过自旋的方式,来进行加锁的。如果要是很快别人就释放锁了,自旋是划算的,但是如果迟迟拿不到锁,一直自旋,并不划算,synchronized自旋不是无休止的自旋,自旋到一定程度之后,就会再次升级成重量级锁(挂起等待锁)。此时,如果线程进行了重量级锁的加锁,并且发生锁竞争,此时线程就会被放到阻塞队列中,暂时不参与CPU调度了,然后直到锁被释放了,这个线程才有机会被调度到,并且有机会获取到锁。

另外,锁升级后不能降级了。

三、锁消除

编译器智能的判定,看当前的代码是否是真的要加锁,如果这个场景不需要加锁,程序猿也加了,那么就会自动把锁给干掉。比如:StringBuffer 带有synchronized,但是如果在单线程中使用StringBuffer, synchronized加了也白加,此时编译器就会直接把这些加锁操作干掉了。

四、锁粗化

锁的粒度: synchronized包含的代码越多,粒度就越粗;包含的代码越少,粒度就越细。

通常情况下,认为锁的粒度细一点比较好。加锁的部分的代码,是不能并发执行的,锁的粒度越细,能并发的代码就越多;反之就越少。

但是有些情况下,锁的粒度粗一些反而更好,两次加锁解锁之间,间隙非常小,此时,不如就直接一次大锁搞定得了。每次加锁可是都有开销的,并发节省的时间,反而不如加锁的开销大。

  • 18
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

crazy_xieyi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值